From d547f87da5f68c12dede7c9d45618cae11ff5699 Mon Sep 17 00:00:00 2001 From: Matt Windsor Date: Fri, 18 Mar 2011 08:28:09 +0000 Subject: Mega-commit to the rescue! Added Javadoc snapshot (admittedly old); show UI now fixed-layout; UI uses system selection colours for accents; now uses bapsserver password and can thus talk to show database relations; removed member relation dependencies until further notice; attempted to get application and applet launchers working but having issues with the latter; started working on a server communicating via a minimal implementation of HTTP 1.1 (standardisation required eventually). --- src/uk/org/ury/client/Client.java | 65 ++++ src/uk/org/ury/client/test/ClientTest.java | 64 +++ src/uk/org/ury/config/ConfigReader.java | 4 +- src/uk/org/ury/database/DatabaseDriver.java | 29 +- src/uk/org/ury/database/DatabaseItem.java | 30 ++ .../org/ury/frontend/AbstractFrontendModule.java | 11 +- src/uk/org/ury/frontend/FrontendApplet.java | 343 ++++++++++++++++ src/uk/org/ury/frontend/FrontendControlPanel.java | 18 +- src/uk/org/ury/frontend/FrontendError.java | 15 +- src/uk/org/ury/frontend/FrontendFrame.java | 125 +++++- src/uk/org/ury/frontend/FrontendMaster.java | 45 ++- src/uk/org/ury/frontend/FrontendModulePanel.java | 10 +- src/uk/org/ury/frontend/FrontendPanel.java | 42 +- src/uk/org/ury/frontend/FrontendSubBanner.java | 5 +- .../frontend/exceptions/LoadFailureException.java | 44 +++ .../exceptions/UICreationFailureException.java | 44 +++ src/uk/org/ury/library/LibraryRequestHandler.java | 144 +++++++ src/uk/org/ury/library/LibraryUtils.java | 112 +++++- src/uk/org/ury/library/item/LibraryItem.java | 26 ++ .../org/ury/library/item/LibraryItemProperty.java | 62 +++ .../org/ury/library/viewer/LibraryTableModel.java | 184 +++++++++ src/uk/org/ury/library/viewer/LibraryViewer.java | 95 +---- .../org/ury/library/viewer/LibraryViewerPanel.java | 10 +- .../org/ury/library/viewer/library_viewer_gui.xml | 12 +- src/uk/org/ury/server/RequestHandler.java | 44 +++ src/uk/org/ury/server/Server.java | 432 +++++++++++++++++++++ src/uk/org/ury/server/ServerProtocol.java | 37 ++ src/uk/org/ury/server/ServerRequestHandler.java | 96 +++++ .../server/exceptions/HandleFailureException.java | 46 +++ src/uk/org/ury/server/protocol/Directive.java | 69 ++++ src/uk/org/ury/show/ShowChannel.java | 41 +- src/uk/org/ury/show/ShowUtils.java | 80 +++- src/uk/org/ury/show/item/ShowItem.java | 68 ++++ src/uk/org/ury/show/item/ShowItemProperty.java | 26 ++ src/uk/org/ury/show/viewer/ChannelPanel.java | 52 +-- .../org/ury/show/viewer/LibraryControlPanel.java | 15 + src/uk/org/ury/show/viewer/ShowViewer.java | 131 +++---- src/uk/org/ury/show/viewer/ShowViewerPanel.java | 44 ++- src/uk/org/ury/show/viewer/TrackBin.java | 51 +-- src/uk/org/ury/show/viewer/channel_panel.xml | 2 +- .../org/ury/show/viewer/library_control_panel.xml | 14 +- src/uk/org/ury/show/viewer/show_viewer_gui.xml | 59 ++- src/uk/org/ury/show/viewer/show_viewer_gui_old.xml | 46 +++ .../org/ury/show/viewer/show_viewer_gui_panels.xml | 43 ++ src/uk/org/ury/show/viewer/track_bin.xml | 2 +- src/uk/org/ury/testrig/ApplicationLauncher.java | 32 ++ src/uk/org/ury/testrig/DemoControlPanel.java | 14 + src/uk/org/ury/testrig/DemoMenu.java | 100 ++--- src/uk/org/ury/testrig/DemoMenuPanel.java | 90 +++++ src/uk/org/ury/testrig/Launcher.java | 17 + src/uk/org/ury/testrig/demo_control_panel.xml | 8 +- 51 files changed, 2748 insertions(+), 450 deletions(-) create mode 100644 src/uk/org/ury/client/Client.java create mode 100644 src/uk/org/ury/client/test/ClientTest.java create mode 100644 src/uk/org/ury/frontend/FrontendApplet.java create mode 100644 src/uk/org/ury/frontend/exceptions/LoadFailureException.java create mode 100644 src/uk/org/ury/frontend/exceptions/UICreationFailureException.java create mode 100644 src/uk/org/ury/library/LibraryRequestHandler.java create mode 100644 src/uk/org/ury/library/item/LibraryItem.java create mode 100644 src/uk/org/ury/library/item/LibraryItemProperty.java create mode 100644 src/uk/org/ury/library/viewer/LibraryTableModel.java create mode 100644 src/uk/org/ury/server/RequestHandler.java create mode 100644 src/uk/org/ury/server/Server.java create mode 100644 src/uk/org/ury/server/ServerProtocol.java create mode 100644 src/uk/org/ury/server/ServerRequestHandler.java create mode 100644 src/uk/org/ury/server/exceptions/HandleFailureException.java create mode 100644 src/uk/org/ury/server/protocol/Directive.java create mode 100644 src/uk/org/ury/show/item/ShowItem.java create mode 100644 src/uk/org/ury/show/item/ShowItemProperty.java create mode 100644 src/uk/org/ury/show/viewer/show_viewer_gui_old.xml create mode 100644 src/uk/org/ury/show/viewer/show_viewer_gui_panels.xml create mode 100644 src/uk/org/ury/testrig/ApplicationLauncher.java create mode 100644 src/uk/org/ury/testrig/DemoMenuPanel.java create mode 100644 src/uk/org/ury/testrig/Launcher.java (limited to 'src') diff --git a/src/uk/org/ury/client/Client.java b/src/uk/org/ury/client/Client.java new file mode 100644 index 0000000..f0b2679 --- /dev/null +++ b/src/uk/org/ury/client/Client.java @@ -0,0 +1,65 @@ +package uk.org.ury.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; + +public class Client +{ + /** + * Get a raw response from the server. + * + * @param file The "file", including path and query string, to + * fetch from the server. + * + * @return The response from the server, as a List of lines. + */ + + public List + get (String file) + { + URL url = null; + URLConnection uc = null; + List result = new ArrayList (); + + try + { + url = new URL ("http://localhost:8000" + file); + } + catch (MalformedURLException e) + { + // TODO Auto-generated catch block + e.printStackTrace (); + } + + try + { + uc = url.openConnection (); + + BufferedReader in = new BufferedReader (new InputStreamReader + (uc.getInputStream ())); + + + String inputLine; + + for (inputLine = in.readLine(); + inputLine != null; + inputLine = in.readLine()) + { + result.add (inputLine); + } + } + catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace (); + } + + return result; + } +} diff --git a/src/uk/org/ury/client/test/ClientTest.java b/src/uk/org/ury/client/test/ClientTest.java new file mode 100644 index 0000000..085bebb --- /dev/null +++ b/src/uk/org/ury/client/test/ClientTest.java @@ -0,0 +1,64 @@ +/** + * + */ +package uk.org.ury.client.test; + +import static org.junit.Assert.*; + +import java.util.List; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import uk.org.ury.client.Client; + +/** + * JUnit test for the low-level client logic. + * + * @author Matt Windsor + */ + +public class ClientTest +{ + + /** + * @throws java.lang.Exception + */ + + @Before + public void + setUp () throws Exception + { + } + + + /** + * @throws java.lang.Exception + */ + + @After + public void + tearDown () throws Exception + { + } + + + /** + * Test method for {@link uk.org.ury.client.Client#get(java.lang.String)}. + */ + + @Test + public void + testGet () + { + Client client = new Client (); + + List response = client.get ("/server/ServerRequestHandler?function=test"); + + Assert.assertEquals ("INFO: Test succeeded.", response.get (2)); + } + +} diff --git a/src/uk/org/ury/config/ConfigReader.java b/src/uk/org/ury/config/ConfigReader.java index 04deb49..ed2d852 100644 --- a/src/uk/org/ury/config/ConfigReader.java +++ b/src/uk/org/ury/config/ConfigReader.java @@ -1,7 +1,5 @@ package uk.org.ury.config; -import java.io.File; - import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -54,7 +52,7 @@ public class ConfigReader { try { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - Document doc = docBuilder.parse (new File(configFile)); + Document doc = docBuilder.parse (configFile); doc.getDocumentElement().normalize(); NodeList nList = doc.getElementsByTagName("auth"); diff --git a/src/uk/org/ury/database/DatabaseDriver.java b/src/uk/org/ury/database/DatabaseDriver.java index a7db32e..7c71827 100644 --- a/src/uk/org/ury/database/DatabaseDriver.java +++ b/src/uk/org/ury/database/DatabaseDriver.java @@ -35,7 +35,8 @@ public class DatabaseDriver * Construct a new DatabaseDriver with the given user class. * * @param config The config with login details. - * @param userclass The user class to log in to the database with. + * + * @param type The user class to log in to the database with. * * @throws IllegalArgumentException if the user class is * not supported (this should not happen). @@ -49,7 +50,8 @@ public class DatabaseDriver */ public - DatabaseDriver (ConfigReader config, UserClass type) throws MissingCredentialsException, ConnectionFailureException + DatabaseDriver (ConfigReader config, UserClass type) + throws MissingCredentialsException, ConnectionFailureException { try { @@ -73,7 +75,8 @@ public class DatabaseDriver */ private void - connect (ConfigReader config, UserClass type) throws SQLException + connect (ConfigReader config, UserClass type) + throws SQLException { if (config == null) throw new IllegalArgumentException ("Supplied null config."); @@ -113,23 +116,18 @@ public class DatabaseDriver * @param fetchSize The maximum number of query rows to return. * * @return the JDBC results set. + * + * @throws SQLException if a SQL error occurs. */ public ResultSet executeQuery (String sql, int fetchSize) + throws SQLException { - try - { - Statement st = conn.createStatement (); - st.setFetchSize (fetchSize); + Statement st = conn.createStatement (); + st.setFetchSize (fetchSize); - return st.executeQuery (sql); - } - catch (SQLException e) - { - e.printStackTrace (); - return null; - } + return st.executeQuery (sql); } @@ -154,7 +152,8 @@ public class DatabaseDriver */ public ResultSet - executeQuery (String sql, Object[] params, int fetchSize) throws SQLException + executeQuery (String sql, Object[] params, int fetchSize) + throws SQLException { PreparedStatement st = conn.prepareStatement (sql); diff --git a/src/uk/org/ury/database/DatabaseItem.java b/src/uk/org/ury/database/DatabaseItem.java index 4f6d34d..f151dbf 100644 --- a/src/uk/org/ury/database/DatabaseItem.java +++ b/src/uk/org/ury/database/DatabaseItem.java @@ -1,8 +1,11 @@ package uk.org.ury.database; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import uk.org.ury.database.exceptions.MissingPropertyException; +import uk.org.ury.server.protocol.Directive; /** @@ -21,6 +24,7 @@ public abstract class DatabaseItem { private Map properties; + /** * Construct a new item from an existing list of properties. * @@ -67,4 +71,30 @@ public abstract class DatabaseItem else throw new MissingPropertyException (property.toString ()); } + + + /** + * Map down the item into a server response body. + * + * This relies on E and T having meaningful toString methods. + * + * @return a list of lines representing the response. + */ + + public List + asResponse () + { + // TODO: Fan out implementation details into separate class + + List response = new ArrayList (); + + for (E property : properties.keySet ()) + { + if (properties.get (property) != null) + response.add (property.toString () + ": " + + properties.get (property).toString ()); + } + + return response; + } } diff --git a/src/uk/org/ury/frontend/AbstractFrontendModule.java b/src/uk/org/ury/frontend/AbstractFrontendModule.java index 99ff9cf..b5b55b6 100644 --- a/src/uk/org/ury/frontend/AbstractFrontendModule.java +++ b/src/uk/org/ury/frontend/AbstractFrontendModule.java @@ -1,6 +1,5 @@ package uk.org.ury.frontend; -import javax.swing.JApplet; /** * An abstract implementation of the FrontendModule interface. @@ -9,7 +8,7 @@ import javax.swing.JApplet; * */ -public abstract class AbstractFrontendModule extends JApplet implements FrontendModule +public abstract class AbstractFrontendModule implements FrontendModule { /** @@ -17,11 +16,5 @@ public abstract class AbstractFrontendModule extends JApplet implements Frontend */ private static final long serialVersionUID = 5309585577127763538L; - - /** - * Initialise the module as an applet. - */ - - public abstract void - init (); + /* Space for rent */ } diff --git a/src/uk/org/ury/frontend/FrontendApplet.java b/src/uk/org/ury/frontend/FrontendApplet.java new file mode 100644 index 0000000..18f0c7a --- /dev/null +++ b/src/uk/org/ury/frontend/FrontendApplet.java @@ -0,0 +1,343 @@ +/** + * + */ +package uk.org.ury.frontend; + +import java.awt.BorderLayout; +import java.awt.Dimension; + +import javax.swing.JApplet; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import uk.org.ury.frontend.exceptions.LoadFailureException; +import uk.org.ury.testrig.Launcher; + +/** + * A frame that hosts a FrontendModulePanel, used for serving frontend + * panels in a window (application mode). + * + * @author Matt Windsor + * + */ + +public class FrontendApplet extends JApplet implements FrontendMaster, Launcher +{ + /** + * + */ + + private static final long serialVersionUID = 740928181256928433L; + + private FrontendModulePanel child; + private FrontendControlPanel cpanel; + + + /** + * Main method. + * + * @param args The command-line arguments to the program. These + * will currently be ignored. + */ + + @Override + public void + init () + { + try + { + javax.swing.SwingUtilities.invokeAndWait (new Runnable() + { + public void + run () + { + try + { + loadModule (DEFAULT_MODULE_NAME); + } + catch (LoadFailureException e) + { + // TODO Auto-generated catch block + e.printStackTrace (); + } + setupUI (); + } + }); + } + catch (Exception e) + { + e.printStackTrace (); + System.err.println("createGUI didn't successfully complete"); + } + } + + + /** + * Set up the user interface of the frame. + */ + + @Override + public void + setupUI () + { + try + { + // Set System L&F + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName ()); + } + catch (UnsupportedLookAndFeelException e) + { + // handle exception + } + catch (ClassNotFoundException e) + { + // handle exception + } + catch (InstantiationException e) + { + // handle exception + } + catch (IllegalAccessException e) + { + // handle exception + } + + + // Composition + + add (child, BorderLayout.CENTER); + + setPreferredSize (new Dimension (800, 600)); + setMinimumSize (new Dimension (800, 600)); + + setVisible (true); + } + + + /** + * Load a module into the frontend frame. + * + * Loading will fail with a fatal error if the class is not found, + * or is not an implementor of FrontendModule. + * + * @param moduleName The fully qualified class-name of the module, + * minus the leading "uk.org.ury." domain. + * + * @throws LoadFailureException if the class is + * not found, or is not an implementor of + * FrontendModule. + */ + + @Override + public void + loadModule (String moduleName) + throws LoadFailureException + { + Class moduleClass = null; + + try + { + moduleClass = Class.forName ("uk.org.ury." + moduleName); + } + catch (ClassNotFoundException e) + { + throw new LoadFailureException ("Could not load module: " + + e.getMessage ()); + } + + + if (FrontendModule.class.isAssignableFrom (moduleClass) == false) + { + throw new LoadFailureException ("Could not load module: Not a FrontendModule"); + } + else + { + FrontendModulePanel temp = child; + + try + { + child = ((FrontendModule) moduleClass.newInstance ()).runFrontend (this); + } + catch (InstantiationException e) + { + throw new LoadFailureException ("Could not load module: " + + e.getMessage ()); + } + catch (IllegalAccessException e) + { + throw new LoadFailureException ("Could not load module: " + + e.getMessage ()); + } + + if (temp != null) + remove (temp); + + getContentPane ().add (child, BorderLayout.CENTER); + child.setMaster (this); + + repaint (); + } + } + + + /** + * Load a module into the frontend frame, additionally installing + * a control panel to communicate with the previous module. + * + * Loading will fail with a fatal error if the class is not found, + * or is not an implementor of FrontendModule. + * + * @param moduleName The fully qualified class-name of the module, + * minus the leading "uk.org.ury." domain. + * + * @param cPanelName The fully qualified class-name of the control + * panel to install, minus the leading + * "uk.org.ury." domain. + * + * @throws LoadFailureException if the class is + * not found, or is not an implementor of + * FrontendModule. + */ + + @Override + public void + loadModule (String moduleName, String cPanelName) + throws LoadFailureException + { + FrontendModulePanel newParent = child; + loadModule (moduleName); + FrontendModulePanel newChild = child; + + loadControlPanel (cPanelName, newParent, newChild); + } + + + /** + * Load and install a control panel class given the class name. + * + * @param cPanelName The fully qualified class-name of the control + * panel to load, minus the leading + * "uk.org.ury." domain. + * + * @param parent The parent panel in the relationship modelled + * by the control panel interface. + * + * @param child The child panel in the relationship modelled + * by the control panel interface. + * + * @throws LoadFailureException if the class is + * not found, or is not an implementor of + * FrontendControlPanel. + */ + + private void + loadControlPanel (String cPanelName, FrontendModulePanel parent, + FrontendModulePanel child) + throws LoadFailureException + { + Class cPanelClass = null; + + try + { + cPanelClass = Class.forName ("uk.org.ury." + cPanelName); + } + catch (ClassNotFoundException e) + { + throw new LoadFailureException ("Could not load control panel: " + + e.getMessage ()); + } + + + if (FrontendControlPanel.class.isAssignableFrom (cPanelClass)) + { + FrontendControlPanel temp = cpanel; + + try + { + cpanel = ((FrontendControlPanel) cPanelClass.newInstance ()); + } + catch (InstantiationException e) + { + throw new LoadFailureException ("Could not load control panel: " + + e.getMessage ()); + } + catch (IllegalAccessException e) + { + throw new LoadFailureException ("Could not load control panel: " + + e.getMessage ()); + } + + if (temp != null) + remove (temp); + + cpanel.setPanels (parent, child); + cpanel.setMaster (this); + cpanel.setPreviousCPanel (temp); + + add (cpanel, BorderLayout.SOUTH); + repaint (); + } + } + + + /** + * Restore an existing module and control panel into the frontend + * frame. + * + * @param mpanel The module panel to restore. + * + * @param cpanel The control panel to restore, if any. A null + * value signifies a lack of control panel. + * + * @throws IllegalArgumentException if the mpanel is null. + */ + + @Override + public void + restoreModule (FrontendModulePanel mpanel, + FrontendControlPanel cpanel) + { + if (mpanel == null) + throw new IllegalArgumentException ("mpanel is null."); + + remove (child); + remove (this.cpanel); + + child = mpanel; + add (child); + + if (cpanel != null) + add (cpanel, BorderLayout.SOUTH); + + this.cpanel = cpanel; + + repaint (); + } + + + /** + * Report a fatal error, + * + * @param message The message, eg the exception message, to report + * to the user. + */ + + @Override + public void + fatalError (String message) + { + FrontendError.reportFatal (message, this); + } + + + /** + * @return the resource directory. + */ + + @Override + public String + getResourceDirectory () + { + return getCodeBase () + "res/"; + } +} \ No newline at end of file diff --git a/src/uk/org/ury/frontend/FrontendControlPanel.java b/src/uk/org/ury/frontend/FrontendControlPanel.java index 5b7f486..b79021a 100644 --- a/src/uk/org/ury/frontend/FrontendControlPanel.java +++ b/src/uk/org/ury/frontend/FrontendControlPanel.java @@ -3,6 +3,8 @@ */ package uk.org.ury.frontend; +import uk.org.ury.frontend.exceptions.UICreationFailureException; + /** * Abstract class for frontend module control panels. @@ -38,26 +40,16 @@ public abstract class FrontendControlPanel extends FrontendPanel * @param xmlPath The path, relative from this source file, to the * XML file from which this panel will read its * layout. + * + * @throws UICreationFailureException if the UI creation fails. */ public FrontendControlPanel (String xmlPath) + throws UICreationFailureException { super (xmlPath, null); } - - - /** - * Set the frontend master to which this panel is bound. - * - * @param master The master to set. - */ - - public void - setMaster (FrontendMaster master) - { - this.master = master; - } /** diff --git a/src/uk/org/ury/frontend/FrontendError.java b/src/uk/org/ury/frontend/FrontendError.java index a08b966..4a13c0a 100644 --- a/src/uk/org/ury/frontend/FrontendError.java +++ b/src/uk/org/ury/frontend/FrontendError.java @@ -29,8 +29,8 @@ public class FrontendError /** * Create an error dialogue to report a fatal error. * - * @string message The message, eg the exception message, - * to report to the user. + * @param message The message, eg the exception message, + * to report to the user. */ public static void @@ -47,4 +47,15 @@ public class FrontendError System.exit (-1); } + + + public static void + reportFatal (String message, FrontendApplet panel) + { + // TODO: Log + + // TODO: Error dialogue + + System.out.println (message); + } } diff --git a/src/uk/org/ury/frontend/FrontendFrame.java b/src/uk/org/ury/frontend/FrontendFrame.java index aabdfbd..39cb89b 100644 --- a/src/uk/org/ury/frontend/FrontendFrame.java +++ b/src/uk/org/ury/frontend/FrontendFrame.java @@ -11,6 +11,8 @@ import javax.swing.JFrame; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; +import uk.org.ury.frontend.exceptions.LoadFailureException; + /** * A frame that hosts a FrontendModulePanel, used for serving frontend * panels in a window (application mode). @@ -31,11 +33,39 @@ public class FrontendFrame extends JFrame implements FrontendMaster private FrontendModulePanel child; private FrontendControlPanel cpanel; + + /** + * Construct a new FrontendFrame given an initial frontend module. + * + * Loading will fail with a fatal error if the class is not found, + * or is not an implementor of FrontendModule. + * + * @param moduleName The fully qualified class-name of the module, + * minus the leading "uk.org.ury." domain. + */ + public - FrontendFrame (FrontendModulePanel parent) + FrontendFrame (String moduleName) + { + super ("URY newBAPS"); + try + { + loadModule (moduleName); + } + catch (LoadFailureException e) + { + fatalError (e.getMessage ()); + } + } + + + /** + * Set up the user interface of the frame. + */ + + public void + setupUI () { - super (parent.getName ()); - try { // Set System L&F @@ -43,7 +73,7 @@ public class FrontendFrame extends JFrame implements FrontendMaster } catch (UnsupportedLookAndFeelException e) { - // handle exception + // handle exception } catch (ClassNotFoundException e) { @@ -60,21 +90,19 @@ public class FrontendFrame extends JFrame implements FrontendMaster setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); - this.child = parent; - Container cp = getContentPane (); // Banner - - banner = new FrontendBanner (parent.getName ()); + System.out.println (child); + banner = new FrontendBanner (child.getName ()); // Composition cp.add (banner, BorderLayout.NORTH); - cp.add (parent, BorderLayout.CENTER); + cp.add (child, BorderLayout.CENTER); setPreferredSize (new Dimension (800, 600)); - setMinimumSize (new Dimension (800, 600)); + setMinimumSize (new Dimension (800, 600)); pack (); setVisible (true); @@ -89,11 +117,16 @@ public class FrontendFrame extends JFrame implements FrontendMaster * * @param moduleName The fully qualified class-name of the module, * minus the leading "uk.org.ury." domain. + * + * @throws LoadFailureException if the class is + * not found, or is not an implementor of + * FrontendModule. */ @Override public void loadModule (String moduleName) + throws LoadFailureException { Class moduleClass = null; @@ -103,11 +136,16 @@ public class FrontendFrame extends JFrame implements FrontendMaster } catch (ClassNotFoundException e) { - FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this); + throw new LoadFailureException ("Could not load module: " + + e.getMessage ()); } - if (FrontendModule.class.isAssignableFrom (moduleClass)) + if (FrontendModule.class.isAssignableFrom (moduleClass) == false) + { + throw new LoadFailureException ("Could not load module: Not a FrontendModule"); + } + else { FrontendModulePanel temp = child; @@ -117,17 +155,24 @@ public class FrontendFrame extends JFrame implements FrontendMaster } catch (InstantiationException e) { - FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this); + throw new LoadFailureException ("Could not load module: " + + e.getMessage ()); } catch (IllegalAccessException e) { - FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this); + throw new LoadFailureException ("Could not load module: " + + e.getMessage ()); } - remove (temp); + if (temp != null) + remove (temp); + add (child); + child.setMaster (this); + + if (banner != null) + banner.setTitle (child.getName ()); - banner.setTitle (child.getName ()); pack (); } } @@ -146,11 +191,16 @@ public class FrontendFrame extends JFrame implements FrontendMaster * @param cPanelName The fully qualified class-name of the control * panel to install, minus the leading * "uk.org.ury." domain. + * + * @throws LoadFailureException if the class is + * not found, or is not an implementor of + * FrontendModule. */ @Override public void loadModule (String moduleName, String cPanelName) + throws LoadFailureException { FrontendModulePanel newParent = child; loadModule (moduleName); @@ -172,11 +222,16 @@ public class FrontendFrame extends JFrame implements FrontendMaster * * @param child The child panel in the relationship modelled * by the control panel interface. + * + * @throws LoadFailureException if the class is + * not found, or is not an implementor of + * FrontendControlPanel. */ - + private void loadControlPanel (String cPanelName, FrontendModulePanel parent, FrontendModulePanel child) + throws LoadFailureException { Class cPanelClass = null; @@ -186,7 +241,8 @@ public class FrontendFrame extends JFrame implements FrontendMaster } catch (ClassNotFoundException e) { - FrontendError.reportFatal ("Could not load control panel: " + e.getMessage (), this); + throw new LoadFailureException ("Could not load control panel: " + + e.getMessage ()); } @@ -200,11 +256,13 @@ public class FrontendFrame extends JFrame implements FrontendMaster } catch (InstantiationException e) { - FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this); + throw new LoadFailureException ("Could not load control panel: " + + e.getMessage ()); } catch (IllegalAccessException e) { - FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this); + throw new LoadFailureException ("Could not load control panel: " + + e.getMessage ()); } if (temp != null) @@ -255,4 +313,31 @@ public class FrontendFrame extends JFrame implements FrontendMaster pack (); repaint (); } + + + /** + * Report a fatal error, + * + * @param message The message, eg the exception message, to report + * to the user. + */ + + @Override + public void + fatalError (String message) + { + FrontendError.reportFatal (message, this); + } + + + /** + * @return the resource directory. + */ + + @Override + public String + getResourceDirectory () + { + return "res/"; + } } diff --git a/src/uk/org/ury/frontend/FrontendMaster.java b/src/uk/org/ury/frontend/FrontendMaster.java index c169d04..0a89e89 100644 --- a/src/uk/org/ury/frontend/FrontendMaster.java +++ b/src/uk/org/ury/frontend/FrontendMaster.java @@ -3,6 +3,8 @@ */ package uk.org.ury.frontend; +import uk.org.ury.frontend.exceptions.LoadFailureException; + /** * Interface for classes providing the parent unit of a frontend @@ -24,10 +26,15 @@ public interface FrontendMaster * * @param moduleName The fully qualified class-name of the module, * minus the leading "uk.org.ury." domain. + * + * @throws LoadFailureException if the class is + * not found, or is not an implementor of + * FrontendModule. */ public void - loadModule (String moduleName); + loadModule (String moduleName) + throws LoadFailureException; /** @@ -40,13 +47,18 @@ public interface FrontendMaster * @param moduleName The fully qualified class-name of the module, * minus the leading "uk.org.ury." domain. * - * @param cpanelName The fully qualified class-name of the control + * @param cPanelName The fully qualified class-name of the control * panel to install, minus the leading * "uk.org.ury." domain. + * + * @throws LoadFailureException if the class is + * not found, or is not an implementor of + * FrontendModule. */ public void - loadModule (String moduleName, String cPanelName); + loadModule (String moduleName, String cPanelName) + throws LoadFailureException; /** @@ -62,4 +74,31 @@ public interface FrontendMaster public void restoreModule (FrontendModulePanel mpanel, FrontendControlPanel cpanel); + + + /** + * Report a fatal error, + * + * @param message The message, eg the exception message, to report + * to the user. + */ + + public void + fatalError (String message); + + + /** + * Set up the frontend master's user interface. + */ + + public void + setupUI (); + + + /** + * @return the resource directory. + */ + + public String + getResourceDirectory (); } diff --git a/src/uk/org/ury/frontend/FrontendModulePanel.java b/src/uk/org/ury/frontend/FrontendModulePanel.java index 148875f..f5009c4 100644 --- a/src/uk/org/ury/frontend/FrontendModulePanel.java +++ b/src/uk/org/ury/frontend/FrontendModulePanel.java @@ -3,6 +3,8 @@ */ package uk.org.ury.frontend; +import uk.org.ury.frontend.exceptions.UICreationFailureException; + /** * A frontend user interface panel. @@ -52,11 +54,14 @@ public abstract class FrontendModulePanel extends FrontendPanel * layout. * * @param master The FrontendMaster driving the frontend. + * + * @throws UICreationFailureException if the UI creation fails. */ public FrontendModulePanel (FrontendModule module, String xmlPath, FrontendMaster master) + throws UICreationFailureException { super (xmlPath, master); this.module = module; @@ -82,9 +87,4 @@ public abstract class FrontendModulePanel extends FrontendPanel { return module; } - - - /** - * - */ } diff --git a/src/uk/org/ury/frontend/FrontendPanel.java b/src/uk/org/ury/frontend/FrontendPanel.java index 0ec8003..931f86b 100644 --- a/src/uk/org/ury/frontend/FrontendPanel.java +++ b/src/uk/org/ury/frontend/FrontendPanel.java @@ -6,11 +6,18 @@ import javax.swing.JPanel; import org.swixml.SwingEngine; +import uk.org.ury.frontend.exceptions.UICreationFailureException; + /** * An extension of JPanel providing common functionality for user * interface panels in the URY system frontend. * + * Most notably, this includes automated access to XML-based + * preparation of the user interface provided by the panel, + * using an appropriate constructor call giving the XML file from + * which the user interface form should be read. + * * @author Matt Windsor * */ @@ -27,7 +34,9 @@ public class FrontendPanel extends JPanel /** * Construct a new, blank FrontendPanel. * - * @param master The FrontendMaster driving the frontend. + * @param master The FrontendMaster driving the frontend, if any. + * For direct instantiations of this class, + * providing null here is guaranteed to be safe. */ public @@ -43,17 +52,22 @@ public class FrontendPanel extends JPanel * Construct a new FrontendPanel from an XML layout. * * This is the preferred means of constructing FrontendPanels, and - * uses SWIXml to construct the panel layout. + * uses an XML-based engine to construct the panel layout. * * @param xmlPath The path, relative from this source file, to the * XML file from which this panel will read its * layout. * - * @param master The FrontendMaster driving the frontend. + * @param master The FrontendMaster driving the frontend, if any. + * For direct instantiations of this class, + * providing null here is guaranteed to be safe. + * + * @throws UICreationFailureException if the UI creation fails. */ public FrontendPanel (String xmlPath, FrontendMaster master) + throws UICreationFailureException { super (); @@ -65,8 +79,10 @@ public class FrontendPanel extends JPanel URL path = getClass ().getResource (xmlPath); if (path == null) - FrontendError.reportFatal ("UI creation failure: XML layout " - + xmlPath + " does not exist.", null); + throw new UICreationFailureException ("UI creation failure:" + + "XML layout " + + xmlPath + + " does not exist."); SwingEngine se = new SwingEngine (this); @@ -85,7 +101,21 @@ public class FrontendPanel extends JPanel } catch (Exception e) { - FrontendError.reportFatal ("UI creation failure: " + e.getMessage (), null); + throw new UICreationFailureException ("UI creation failure: " + + e.getMessage ()); } } + + + /** + * Set the frontend master. + * + * @param master The new frontend master to use. + */ + + public void + setMaster (FrontendMaster master) + { + this.master = master; + } } diff --git a/src/uk/org/ury/frontend/FrontendSubBanner.java b/src/uk/org/ury/frontend/FrontendSubBanner.java index da162bb..6942fe1 100644 --- a/src/uk/org/ury/frontend/FrontendSubBanner.java +++ b/src/uk/org/ury/frontend/FrontendSubBanner.java @@ -2,7 +2,6 @@ package uk.org.ury.frontend; import javax.swing.BorderFactory; import javax.swing.JLabel; -import javax.swing.JTextArea; import javax.swing.UIManager; @@ -15,6 +14,10 @@ import javax.swing.UIManager; public class FrontendSubBanner extends JLabel { + /** + * + */ + private static final long serialVersionUID = 7843563245601622086L; private static final String TITLE_PREFIX = ""; private static final String TITLE_SUFFIX = ""; diff --git a/src/uk/org/ury/frontend/exceptions/LoadFailureException.java b/src/uk/org/ury/frontend/exceptions/LoadFailureException.java new file mode 100644 index 0000000..691eaa0 --- /dev/null +++ b/src/uk/org/ury/frontend/exceptions/LoadFailureException.java @@ -0,0 +1,44 @@ +/** + * + */ +package uk.org.ury.frontend.exceptions; + + +/** + * Exception thrown when the loading of a new frontend module fails. + * + * @author Matt Windsor + */ + +public class LoadFailureException extends Exception +{ + /** + * + */ + private static final long serialVersionUID = -7353531873142099828L; + + +/** + * Construct a new LoadFailureException with a + * default reason. + */ + + public + LoadFailureException () + { + super ("Module load failure."); + } + + + /** + * Construct a new LoadFailureException. + * + * @param reason The explanation for the exception. + */ + + public + LoadFailureException (String reason) + { + super (reason); + } +} diff --git a/src/uk/org/ury/frontend/exceptions/UICreationFailureException.java b/src/uk/org/ury/frontend/exceptions/UICreationFailureException.java new file mode 100644 index 0000000..6d51ef3 --- /dev/null +++ b/src/uk/org/ury/frontend/exceptions/UICreationFailureException.java @@ -0,0 +1,44 @@ +/** + * + */ +package uk.org.ury.frontend.exceptions; + + +/** + * Exception thrown when the creation of a UI element fails. + * + * @author Matt Windsor + */ + +public class UICreationFailureException extends Exception +{ + /** + * + */ + private static final long serialVersionUID = -7353531873142099828L; + + +/** + * Construct a new UICreationFailureException with a + * default reason. + */ + + public + UICreationFailureException () + { + super ("UI creation failure."); + } + + + /** + * Construct a new UICreationFailureException. + * + * @param reason The explanation for the exception. + */ + + public + UICreationFailureException (String reason) + { + super (reason); + } +} diff --git a/src/uk/org/ury/library/LibraryRequestHandler.java b/src/uk/org/ury/library/LibraryRequestHandler.java new file mode 100644 index 0000000..30bb7fc --- /dev/null +++ b/src/uk/org/ury/library/LibraryRequestHandler.java @@ -0,0 +1,144 @@ +/** + * + */ +package uk.org.ury.library; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import uk.org.ury.database.DatabaseDriver; +import uk.org.ury.database.UserClass; +import uk.org.ury.database.exceptions.ConnectionFailureException; +import uk.org.ury.database.exceptions.MissingCredentialsException; +import uk.org.ury.database.exceptions.QueryFailureException; +import uk.org.ury.library.exceptions.EmptySearchException; +import uk.org.ury.library.item.LibraryItem; +import uk.org.ury.server.Server; +import uk.org.ury.server.RequestHandler; +import uk.org.ury.server.exceptions.HandleFailureException; +import uk.org.ury.server.protocol.Directive; + +/** + * A request handler for library queries. + * + * @author Matt Windsor + */ + +public class LibraryRequestHandler implements RequestHandler +{ + /** + * Handle a server GET request (that is, a request for data + * output). + * + * @param parameters A key-value map of parameters supplied with + * the server request. Typically, the function + * parameter will detail the function that the + * request handler is expected to perform. + * + * @param server The server from which the request originated. + * This will be able to provide the handler with + * pooled resources, for example the database. + * + * @return A list of lines to return in the body of the + * server's response to the client. + * + * @throws HandleFailureException if the handler cannot + * handle the request. + */ + + @Override + public List + handleGetRequest (Map parameters, Server server) + throws HandleFailureException + { + List response = new ArrayList (); + + if (parameters.containsKey ("function")) + { + String function = parameters.get ("function"); + + if (function.equals ("search")) + { + doSearch (parameters, response, server); + } + else if (function.equals ("help")) + { + response.add ("INFO: Available functions:"); + response.add ("INFO: search (string) - search library for string."); + } + else + throw new HandleFailureException ("Unknown function: " + + function + ". (Try 'function=help'.)"); + + } + else + throw new HandleFailureException ("No function provided. (Try 'function=help'.)"); + + return response; + } + + + /** + * Perform a library search, populating the response list. + * + * @param parameters A key-value map of parameters supplied with + * the server request. Typically, the function + * parameter will detail the function that the + * request handler is expected to perform. + * + * @param response The response list to populate. + * + * @param server The server providing database resources. + * + * @throws HandleFailureException if an error occurs + * that thwarts the handling of the request. + */ + + private void + doSearch (Map parameters, + List response, Server server) + throws HandleFailureException + { + if (parameters.containsKey ("search") == false) + throw new HandleFailureException ("Search term is missing."); + else if (parameters.get ("search") == null) + throw new HandleFailureException ("Search term is null."); + + String search = parameters.get ("search"); + DatabaseDriver dd = null; + + try + { + dd = server.getDatabaseConnection (UserClass.READ_ONLY); + } + catch (MissingCredentialsException e) + { + throw new HandleFailureException (e.getMessage ()); + } + catch (ConnectionFailureException e) + { + throw new HandleFailureException (e.getMessage ()); + } + + try + { + for (LibraryItem li : LibraryUtils.search (dd, search)) + { + response.add (Directive.ITEM_START.toString ()); + + response.addAll (li.asResponse ()); + + response.add (Directive.ITEM_END.toString ()); + } + } + catch (QueryFailureException e) + { + throw new HandleFailureException (e.getMessage ()); + } + catch (EmptySearchException e) + { + throw new HandleFailureException (e.getMessage ()); + } + } +} diff --git a/src/uk/org/ury/library/LibraryUtils.java b/src/uk/org/ury/library/LibraryUtils.java index a280738..8a71285 100644 --- a/src/uk/org/ury/library/LibraryUtils.java +++ b/src/uk/org/ury/library/LibraryUtils.java @@ -8,12 +8,16 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map; import uk.org.ury.database.DatabaseDriver; import uk.org.ury.database.exceptions.QueryFailureException; -import uk.org.ury.library.LibraryItemProperty; import uk.org.ury.library.exceptions.EmptySearchException; +import uk.org.ury.library.item.LibraryItem; +import uk.org.ury.library.item.LibraryItemProperty; +import uk.org.ury.server.protocol.Directive; /** @@ -77,13 +81,9 @@ public class LibraryUtils + " t.artist, recordlabel AS label, status, media AS medium, format," + " datereleased, EXTRACT(EPOCH FROM dateadded) as dateadded," + " EXTRACT(EPOCH FROM datetime_lastedit) AS dateedited," - + " shelfletter, shelfnumber, cdid, memberid_add, memberid_lastedit," - + " digitised, clean," - + " a.fname AS fnameadd, a.sname AS snameadd, b.fname AS fnameedit, b.sname AS snameedit" + + " shelfletter, shelfnumber, cdid, digitised, clean" + " FROM rec_record AS r" + " INNER JOIN rec_track AS t ON (r.recordid = t.recordid)" - + " INNER JOIN member AS a ON (a.memberid = r.memberid_add)" - + " LEFT JOIN member AS b ON (b.memberid = r.memberid_lastedit)" + " WHERE t.title ILIKE ?" + " OR t.artist ILIKE ?" + " OR r.title ILIKE ?" @@ -126,7 +126,7 @@ public class LibraryUtils { // Translate SQL columns into a list of properties. - HashMap properties = new HashMap (); + Map properties = new HashMap (); for (LibraryItemProperty p : LibraryItemProperty.values ()) { @@ -144,4 +144,102 @@ public class LibraryUtils return new LibraryItem (properties); } + + + /** + * Construct items from a server response body. + * + * @param response The list of strings that constitute the response. + * + * @return a list of LibraryItems corresponding to the item + * stanzas in the response. + */ + + public static List + extractItemsFromResponse (List response) + { + List result = new ArrayList (); + + boolean inItem = false; + List itemBuffer = new ArrayList (); + + for (String line : response) + { + if (inItem == false) + { + if (line.startsWith (Directive.ITEM_START.toString ())) + { + inItem = true; + itemBuffer.clear (); + } + } + + if (inItem == true) + { + itemBuffer.add (line); + + if (line.startsWith (Directive.ITEM_END.toString ())) + { + inItem = false; + result.add (createItemFromResponse (itemBuffer)); + } + } + } + + return result; + } + + + /** + * Construct a new item from a server response fragment. + * + * @param response The list of strings that constitutes the response. + * The list must begin with Directive.ITEM_START and + * end with Directive.ITEM_END's string + * representations and otherwise contain solely + * Directive.ITEM_PROPERTY lines. + * + * @return a LibraryItem embodying the properties described + * in the response fragment. + * + * @throws IllegalArgumentException if the response is + * malformed or null, or if the instantiation of + * DatabaseItem does not use String as its data type. + */ + + public static LibraryItem + createItemFromResponse (List response) + { + // TODO: More appropriate exceptions. + + if (response == null) + throw new IllegalArgumentException ("Response is null."); + else if (response.get (0).equals (Directive.ITEM_START.toString ()) + && response.get (response.size () - 1) + .equals (Directive.ITEM_END.toString ())) + { + // Response of size 2 must be blank. + if (response.size () <= 2) + throw new IllegalArgumentException ("Blank response."); + + Map properties = new HashMap (); + + for (int i = 0; i < response.size () - 1; i++) + { + // TODO: fan out impl. details to separate class + if (response.get (i) + .startsWith (Directive.ITEM_PROPERTY.toString ())) + { + String[] responseTuple = response.get (i).split (":="); + + properties.put (LibraryItemProperty.getFromSQL (responseTuple[1]), + responseTuple[2]); + } + } + + return new LibraryItem (properties); + } + else + throw new IllegalArgumentException ("Malformed response."); + } } diff --git a/src/uk/org/ury/library/item/LibraryItem.java b/src/uk/org/ury/library/item/LibraryItem.java new file mode 100644 index 0000000..d2a790b --- /dev/null +++ b/src/uk/org/ury/library/item/LibraryItem.java @@ -0,0 +1,26 @@ +/** + * + */ +package uk.org.ury.library.item; + + +import java.util.Map; + +import uk.org.ury.database.DatabaseItem; + + +/** + * An item in the URY library. + * + * @author Matt Windsor + */ + +public class LibraryItem extends DatabaseItem +{ + public + LibraryItem (Map properties) + { + super (properties); + } +} \ No newline at end of file diff --git a/src/uk/org/ury/library/item/LibraryItemProperty.java b/src/uk/org/ury/library/item/LibraryItemProperty.java new file mode 100644 index 0000000..44f5f22 --- /dev/null +++ b/src/uk/org/ury/library/item/LibraryItemProperty.java @@ -0,0 +1,62 @@ +package uk.org.ury.library.item; + +/** + * The parameters that are stored in the LibraryItem. + * + * @author Matt Windsor + */ + +public enum LibraryItemProperty + { + // Constant SQL identifier + TITLE ("title"), + ALBUM ("album"), + ARTIST ("artist"), + LABEL ("label"), + STATUS ("status"), + MEDIUM ("medium"), + FORMAT ("format"), + DATE_RELEASED ("datereleased"), + DATE_ADDED ("dateadded"), + DATE_EDITED ("dateedited"), + SHELF_LETTER ("shelfletter"), + SHELF_NUMBER ("shelfnumber"), + CD_ID ("cdid"), + IS_DIGITISED ("digitised"), + IS_CLEAN ("clean"); + + + public final String sql; + + + private + LibraryItemProperty (String sql) + { + this.sql = sql; + } + + + /** + * Retrieve a LibraryItemProperty given its SQL identifier. + * + * @param string The SQL identifier. + * @return The first property to match. + * + * @throws IllegalArgumentException if no matches were + * found. + */ + + public static LibraryItemProperty + getFromSQL (String string) + { + // TODO: Better exception? + + for (LibraryItemProperty prop : values ()) + { + if (prop.sql.equals (string)) + return prop; + } + + throw new IllegalArgumentException ("Nonexistent property SQL."); + } + }; \ No newline at end of file diff --git a/src/uk/org/ury/library/viewer/LibraryTableModel.java b/src/uk/org/ury/library/viewer/LibraryTableModel.java new file mode 100644 index 0000000..1ce5709 --- /dev/null +++ b/src/uk/org/ury/library/viewer/LibraryTableModel.java @@ -0,0 +1,184 @@ +/** + * + */ +package uk.org.ury.library.viewer; + +import java.util.List; + +import javax.swing.table.AbstractTableModel; + +import uk.org.ury.database.exceptions.MissingPropertyException; +import uk.org.ury.library.item.LibraryItem; +import uk.org.ury.library.item.LibraryItemProperty; + + +/** + * A table model for the library viewer. + * + * @author Matt Windsor + */ + +public class LibraryTableModel extends AbstractTableModel +{ + + /** + * + */ + + private static final long serialVersionUID = -1744980619128903509L; + + private List data; + + + /** + * Construct a new table model. + * + * @param data The list of data on which the model will be based. + */ + + public + LibraryTableModel (List data) + { + this.data = data; + } + + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getColumnCount() + */ + + @Override + public int + getColumnCount () + { + return 6; + } + + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getRowCount() + */ + + @Override + public int + getRowCount () + { + return data.size (); + } + + + /** + * @param c The column whose class should be investigated. + * + * @return the column class of column c. + */ + + @Override + public Class + getColumnClass (int c) + { + return getValueAt (0, c).getClass (); + } + + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getValueAt(int, int) + */ + + @Override + public Object + getValueAt (int rowIndex, int columnIndex) + { + LibraryItem li = data.get (rowIndex); + + try + { + String[] columnData = {li.get (LibraryItemProperty.TITLE), + li.get (LibraryItemProperty.ARTIST), + li.get (LibraryItemProperty.ALBUM)}; + + switch (columnIndex) + { + default: // Title, artist, album, unknown + + if (columnIndex >= columnData.length) + return "Unknown"; + else + return columnData[columnIndex]; + + case 3: // Medium + + // TODO: Make this less kludge-y + + String mediumString = li.get (LibraryItemProperty.MEDIUM); + + if (mediumString.equals ("c")) + return "Compact Disc"; + else if (mediumString.equals ("7")) + return "7\" Vinyl"; + else if (mediumString.equals ("2")) + return "12\" Vinyl"; + else + return "Unrecognised"; + + case 4: // Clean? + + // Return true if marked true, false if marked false or unknown etc. + + String cleanString = li.get (LibraryItemProperty.IS_CLEAN); + + // TODO: Nicer way of showing this + + if (cleanString.equals ("y")) + return "Yes"; + else if (cleanString.equals ("n")) + return "No"; + else + return "???"; + + case 5: // isDigitised + + // Return true if marked true, false if marked false or unknown etc. + + String digitisedString = li.get (LibraryItemProperty.IS_DIGITISED); + + if (digitisedString.equals ("t")) + return true; + else + return false; + } + } + catch (MissingPropertyException e) + { + return "Unknown"; + } + } + + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getColumnName(int, int) + */ + + @Override + public String + getColumnName (int index) + { + switch (index) + { + case 0: + return "Title"; + case 1: + return "Artist"; + case 2: + return "Album"; + case 3: + return "Medium"; + case 4: + return "Clean?"; + case 5: + return "On system?"; + default: + return "ERROR"; + } + } +} diff --git a/src/uk/org/ury/library/viewer/LibraryViewer.java b/src/uk/org/ury/library/viewer/LibraryViewer.java index a98fa54..9587d5e 100644 --- a/src/uk/org/ury/library/viewer/LibraryViewer.java +++ b/src/uk/org/ury/library/viewer/LibraryViewer.java @@ -1,27 +1,21 @@ package uk.org.ury.library.viewer; -import java.lang.reflect.InvocationTargetException; - import java.util.ArrayList; import java.util.List; -import javax.swing.SwingUtilities; - import uk.org.ury.config.ConfigReader; import uk.org.ury.database.DatabaseDriver; import uk.org.ury.database.UserClass; import uk.org.ury.database.exceptions.MissingCredentialsException; import uk.org.ury.database.exceptions.QueryFailureException; import uk.org.ury.frontend.AbstractFrontendModule; -import uk.org.ury.frontend.FrontendError; -import uk.org.ury.frontend.FrontendFrame; import uk.org.ury.frontend.FrontendMaster; import uk.org.ury.frontend.FrontendModulePanel; - -import uk.org.ury.library.LibraryItem; +import uk.org.ury.frontend.exceptions.UICreationFailureException; import uk.org.ury.library.LibraryUtils; import uk.org.ury.library.exceptions.EmptySearchException; +import uk.org.ury.library.item.LibraryItem; public class LibraryViewer extends AbstractFrontendModule { @@ -33,7 +27,6 @@ public class LibraryViewer extends AbstractFrontendModule private DatabaseDriver dd; private List libraryList; private LibraryViewerPanel panel; - private FrontendFrame frame; private ConfigReader config; @@ -53,64 +46,9 @@ public class LibraryViewer extends AbstractFrontendModule System.out.println(e); } - frame = null; libraryList = new ArrayList (); panel = null; } - - - /** - * Initialise the library viewer frontend as an applet. - */ - - public void - init () - { - frame = null; - libraryList = new ArrayList (); - panel = null; - - - try - { - SwingUtilities.invokeAndWait (new Runnable () - { - public void - run () - { - panel.setOpaque (true); - setContentPane (panel); - - runFrontend (null); - } - - }); - } - catch (InterruptedException e) - { - // TODO Auto-generated catch block - e.printStackTrace (); - } - catch (InvocationTargetException e) - { - // TODO Auto-generated catch block - e.printStackTrace (); - } - } - - - /** - * Run the library viewer frontend as an applet. - */ - - public void - start () - { - frame = null; - panel = new LibraryViewerPanel (this, null); - - add (panel); - } /** @@ -129,14 +67,22 @@ public class LibraryViewer extends AbstractFrontendModule catch (MissingCredentialsException e) { // TODO: Privilege de-escalation - FrontendError.reportFatal (e.getMessage (), frame); + master.fatalError (e.getMessage ()); } catch (Exception f) { - FrontendError.reportFatal (f.getMessage (), frame); + master.fatalError (f.getMessage ()); } - panel = new LibraryViewerPanel (this, master); + try + { + panel = new LibraryViewerPanel (this, master); + } + catch (UICreationFailureException e) + { + master.fatalError (e.getMessage ()); + } + return panel; } @@ -152,19 +98,16 @@ public class LibraryViewer extends AbstractFrontendModule * * @throws EmptySearchException if the search string is * empty or null (from LibraryUtils.search). + * + * @throws QueryFailureException if the search query + * fails (from LibraryUtils.search). */ public void - doSearch (String search) throws EmptySearchException + doSearch (String search) + throws EmptySearchException, QueryFailureException { - try - { - libraryList = LibraryUtils.search (dd, search); - } - catch (QueryFailureException e) - { - FrontendError.reportFatal (e.getMessage (), frame); - } + libraryList = LibraryUtils.search (dd, search); } diff --git a/src/uk/org/ury/library/viewer/LibraryViewerPanel.java b/src/uk/org/ury/library/viewer/LibraryViewerPanel.java index 7638822..e453095 100644 --- a/src/uk/org/ury/library/viewer/LibraryViewerPanel.java +++ b/src/uk/org/ury/library/viewer/LibraryViewerPanel.java @@ -14,9 +14,10 @@ import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.SwingWorker; +import uk.org.ury.database.exceptions.QueryFailureException; import uk.org.ury.frontend.FrontendMaster; import uk.org.ury.frontend.FrontendModulePanel; -import uk.org.ury.library.LibraryTableModel; +import uk.org.ury.frontend.exceptions.UICreationFailureException; import uk.org.ury.library.exceptions.EmptySearchException; @@ -59,10 +60,13 @@ public class LibraryViewerPanel extends FrontendModulePanel * @param viewer The LibraryViewer controlling this LibraryViewerPanel. * * @param master The FrontendMaster driving the frontend. + * + * @throws UICreationFailureException if the UI creation fails. */ public LibraryViewerPanel (LibraryViewer viewer, FrontendMaster master) + throws UICreationFailureException { super (viewer, "library_viewer_gui.xml", master); @@ -138,6 +142,10 @@ public class LibraryViewerPanel extends FrontendModulePanel { master.doSearch (searchField.getText ()); } + catch (QueryFailureException e) + { + searchFailureMessage = "Search failed: " + e.getMessage (); + } catch (EmptySearchException e) { searchFailureMessage = "Please type in a search term."; diff --git a/src/uk/org/ury/library/viewer/library_viewer_gui.xml b/src/uk/org/ury/library/viewer/library_viewer_gui.xml index 6b7e745..5177e3f 100644 --- a/src/uk/org/ury/library/viewer/library_viewer_gui.xml +++ b/src/uk/org/ury/library/viewer/library_viewer_gui.xml @@ -1,13 +1,11 @@ - -