[15222] | 1 | /**
|
---|
| 2 | *#########################################################################
|
---|
| 3 | * GS3JavaClient.java - part of the demo-client for Greenstone 3, of the
|
---|
| 4 | * Greenstone digital library suite from the New Zealand Digital Library
|
---|
| 5 | * Project at the * University of Waikato, New Zealand.
|
---|
| 6 | * <BR><BR>
|
---|
| 7 | * Copyright (C) 2008 New Zealand Digital Library Project
|
---|
| 8 | * <BR><BR>
|
---|
| 9 | * This program is free software; you can redistribute it and/or modify
|
---|
| 10 | * it under the terms of the GNU General Public License as published by
|
---|
| 11 | * the Free Software Foundation; either version 2 of the License, or
|
---|
| 12 | * (at your option) any later version.
|
---|
| 13 | * <BR><BR>
|
---|
| 14 | * This program is distributed in the hope that it will be useful,
|
---|
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 17 | * GNU General Public License for more details.
|
---|
| 18 | *########################################################################
|
---|
| 19 | */
|
---|
| 20 |
|
---|
| 21 | package org.greenstone.gs3client;
|
---|
| 22 |
|
---|
[15383] | 23 |
|
---|
[15222] | 24 | import org.apache.log4j.Logger;
|
---|
[15237] | 25 | import org.apache.log4j.PropertyConfigurator;
|
---|
[15222] | 26 | import org.greenstone.gs3client.BrowseDisplay.ClassifierData;
|
---|
| 27 |
|
---|
| 28 | import org.greenstone.gs3client.data.BrowseResponseData;
|
---|
| 29 | import org.greenstone.gs3client.data.CollectionData;
|
---|
| 30 | import org.greenstone.gs3client.data.DocumentNodeData;
|
---|
| 31 | import org.greenstone.gs3client.data.ClassifierNodeData;
|
---|
| 32 | import org.greenstone.gs3client.data.NodeData;
|
---|
| 33 | import org.greenstone.gs3client.data.ParseUtil;
|
---|
| 34 | import org.greenstone.gs3client.data.QueryResponseData;
|
---|
| 35 | import org.greenstone.gs3client.data.ResponseData;
|
---|
[15383] | 36 | //By importing this *static* inner class of CollectionData, can refer
|
---|
| 37 | //to it by its unqualified name 'ServiceData'. (Learnt this from
|
---|
| 38 | //http://today.java.net/pub/a/today/2006/03/23/multi-split-pane.html)
|
---|
[15222] | 39 | import org.greenstone.gs3client.data.CollectionData.ServiceData;
|
---|
| 40 | import org.greenstone.gs3client.dlservices.DigitalLibraryServicesAPIA;
|
---|
| 41 | import org.greenstone.gs3client.dlservices.FedoraServicesAPIA;
|
---|
| 42 | import org.greenstone.gs3client.dlservices.GS3ServicesAPIA;
|
---|
| 43 |
|
---|
| 44 | import javax.swing.*;
|
---|
| 45 | import java.awt.BorderLayout;
|
---|
| 46 | import java.awt.GridLayout;
|
---|
| 47 | import java.awt.FlowLayout;
|
---|
| 48 | import java.awt.event.ActionListener;
|
---|
| 49 | import java.awt.event.ActionEvent;
|
---|
| 50 | import java.awt.Container;
|
---|
| 51 | import java.awt.Toolkit; // for making this JFrame client fullsize
|
---|
| 52 |
|
---|
| 53 | import java.net.Authenticator;
|
---|
| 54 | import java.net.PasswordAuthentication;
|
---|
| 55 |
|
---|
| 56 | import org.w3c.dom.Document;
|
---|
| 57 | import org.w3c.dom.Element;
|
---|
| 58 | import org.w3c.dom.NodeList;
|
---|
| 59 |
|
---|
| 60 | import java.util.Vector;
|
---|
| 61 | import java.util.HashMap;
|
---|
| 62 |
|
---|
| 63 | import java.io.StringReader;
|
---|
| 64 | import javax.xml.parsers.DocumentBuilderFactory;
|
---|
| 65 | import javax.xml.parsers.DocumentBuilder;
|
---|
| 66 | import org.xml.sax.InputSource;
|
---|
| 67 |
|
---|
| 68 | import org.greenstone.gsdl3.util.GSXML;
|
---|
| 69 | import java.awt.Cursor;
|
---|
| 70 |
|
---|
| 71 | /*
|
---|
| 72 | To make this class compile with Java 5/Java 1.5 need to rename the file
|
---|
| 73 | xalan.jar.tmp (located in $GS3_HOME/web/WEB-INF/lib) to xalan.jar
|
---|
| 74 | Without doing that, it will complain (unless compiled with Java 1.4.2).
|
---|
| 75 |
|
---|
| 76 | RUNTIME Configuration of this class:
|
---|
| 77 | - this client needs the jar files:
|
---|
| 78 | log4j, xercesImpl, mail, lucene, javagdbm,
|
---|
| 79 | And possibly: xml-apis, activation, axis, mg, mgpp
|
---|
| 80 | - VM arguments: -Djava.library.path=/research/ak19/greenstone3/lib/jni
|
---|
| 81 |
|
---|
| 82 | COMPILE Configuration of this class:
|
---|
| 83 | - BUILD PATH needs the jar files:
|
---|
| 84 | gsdl3 (or just the class GSXML), jaxrpc, axis
|
---|
| 85 | */
|
---|
| 86 | /**
|
---|
| 87 | * The main Javaclient class. Creates the main window containing:
|
---|
| 88 | * - the radio button group for making either Greenstone 3 or Fedora the active DL.
|
---|
| 89 | * - the comboboxes for selecting the collection and the service therein
|
---|
| 90 | * - three panes - for executing queries, viewing search results and browsing.
|
---|
| 91 | * @author ak19
|
---|
| 92 | */
|
---|
| 93 | public class GS3JavaClient extends JFrame implements ActionListener {
|
---|
| 94 | // static final long serialVersionUID = 1; //eclipse keeps warning
|
---|
| 95 | /** The Logger for this class */
|
---|
| 96 | static Logger LOG = Logger.getLogger(GS3JavaClient.class);
|
---|
[15731] | 97 |
|
---|
[15222] | 98 | /** The value of the SEARCHING activity */
|
---|
| 99 | public static int SEARCHING = 0;
|
---|
| 100 | /** The value of the BROWSING activity */
|
---|
| 101 | public static int BROWSING = 1;
|
---|
| 102 | /** we want to display a drop-down box for the services available,
|
---|
| 103 | * but only Services that can be executed (searching and browsing) */
|
---|
| 104 | protected static final boolean executableServicesOnly = true;
|
---|
| 105 |
|
---|
| 106 | /** To keep track of whether we are searching or browsing.
|
---|
| 107 | * Value of activity can be SEARCHING OR BROWSING */
|
---|
| 108 | protected int activity = 0; //
|
---|
| 109 |
|
---|
| 110 | /** Reference to a digital library instance (Greenstone 3 or Fedora) that
|
---|
| 111 | * allows this client to execute services offered by the digital library */
|
---|
| 112 | protected DigitalLibraryServicesAPIA dlAPIA = null;
|
---|
| 113 | /** Reference to the object that interacts with Greenstone3's web services */
|
---|
| 114 | protected GS3ServicesAPIA greenstoneDL = null;
|
---|
| 115 | /** Reference to the object that interacts with the FedoraGS3.jar component */
|
---|
| 116 | protected FedoraServicesAPIA fedoraDL = null;
|
---|
| 117 |
|
---|
| 118 | /** Object that stores the data of a query response XML message */
|
---|
| 119 | protected QueryResponseData queryResponseObj = null;
|
---|
| 120 |
|
---|
| 121 | /** Object that stores the data of a browse response XML message
|
---|
| 122 | * (response for classification hierarchies) */
|
---|
| 123 | protected BrowseResponseData browseResponseObject = null;
|
---|
| 124 |
|
---|
| 125 | /** Preferred language of display items in responses.
|
---|
| 126 | * "" or "en" for English */
|
---|
| 127 | protected String lang = "";
|
---|
| 128 |
|
---|
| 129 | /** The currently selected collection */
|
---|
| 130 | protected String colName = "";
|
---|
| 131 | /** The currently selected service */
|
---|
| 132 | protected String serviceName = "";
|
---|
| 133 |
|
---|
| 134 | /* The always-visible GUI objects of this main window */
|
---|
| 135 | protected JComboBox dlChooser = null;
|
---|
| 136 | protected JTextField proxyhostField = null;
|
---|
| 137 | protected JTextField proxyportField = null;
|
---|
| 138 | protected JTextField nonProxyHostNamesField = null;
|
---|
| 139 | protected JButton setProxySettings = null;
|
---|
| 140 |
|
---|
| 141 | protected JComboBox serviceBox = null;
|
---|
| 142 | protected JComboBox collBox = null;
|
---|
| 143 | protected JButton collInfoButton = null;
|
---|
| 144 | protected JButton searchButton = null;
|
---|
| 145 | protected JTabbedPane tabbedPane = null;
|
---|
| 146 |
|
---|
[26180] | 147 | public static final int SELECT = 0;
|
---|
| 148 | public static final int GREENSTONE = 1;
|
---|
| 149 | public static final int FEDORA = 2;
|
---|
[15222] | 150 | protected static final String[] dlOptions = {"select", "greenstone", "fedora"};
|
---|
| 151 |
|
---|
| 152 | /* Components of the query tab */
|
---|
| 153 | protected QueryForm queryPanel = null;
|
---|
| 154 | protected JTextField collectionNameField = null;
|
---|
| 155 |
|
---|
| 156 | /* Components of the search tab */
|
---|
| 157 | protected SearchResultsDisplay searchResultsDisplay = null;
|
---|
| 158 | protected JPanel searchPanel = null;
|
---|
| 159 | protected JTextArea searchSummary = null;
|
---|
| 160 |
|
---|
| 161 | /* Components of the browse tab */
|
---|
| 162 | protected BrowseDisplay browsePanel = null;
|
---|
| 163 |
|
---|
| 164 | /** @return the language of the display items */
|
---|
| 165 | public String getLanguage() { return lang; }
|
---|
| 166 | /** Set the preferred language of the display items
|
---|
| 167 | * @param lang - the preferred language for display values */
|
---|
| 168 | public void setLanguage(String lang) { this.lang = lang; }
|
---|
| 169 |
|
---|
| 170 | /** Inner class that handles authentication for any sites (urls, etc.)
|
---|
| 171 | * that require it. A dialog pops up to request username and password
|
---|
| 172 | * details from the user for each site's realm that needs authentication.
|
---|
| 173 | */
|
---|
| 174 | static class PasswordAuthenticator extends Authenticator {
|
---|
| 175 | protected PasswordAuthentication getPasswordAuthentication() {
|
---|
| 176 | JTextField username = new JTextField();
|
---|
| 177 | JTextField password = new JPasswordField();
|
---|
| 178 | JPanel panel = new JPanel(new GridLayout(2,2));
|
---|
| 179 | panel.add(new JLabel("User Name"));
|
---|
| 180 | panel.add(username);
|
---|
| 181 | panel.add(new JLabel("Password") );
|
---|
| 182 | panel.add(password);
|
---|
| 183 | int option = JOptionPane.showConfirmDialog(null, new Object[] {
|
---|
| 184 | "Site: "+getRequestingHost(),
|
---|
| 185 | "Realm: "+getRequestingPrompt(), panel},
|
---|
| 186 | "Enter Network Password",
|
---|
| 187 | JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
|
---|
| 188 | if ( option == JOptionPane.OK_OPTION ) {
|
---|
| 189 | return new PasswordAuthentication(
|
---|
| 190 | username.getText(), password.getText().toCharArray());
|
---|
| 191 | } else {
|
---|
| 192 | return null;
|
---|
| 193 | }
|
---|
| 194 | }
|
---|
| 195 | }
|
---|
| 196 |
|
---|
| 197 | /** Default constructor that creates and initialises this main
|
---|
| 198 | * window and its internal GUI components */
|
---|
| 199 | public GS3JavaClient() {
|
---|
| 200 | super();
|
---|
| 201 | this.setTitle("Greenstone 3 web services demo-client");
|
---|
| 202 |
|
---|
| 203 | // digital library panel lets the user choose the digital library
|
---|
| 204 | // repository to access and to set the proxy settings
|
---|
| 205 | JPanel dlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
---|
| 206 | dlChooser = new JComboBox(dlOptions);
|
---|
| 207 | dlPanel.add(new JLabel("Use digital library:"));
|
---|
| 208 | dlPanel.add(dlChooser);
|
---|
| 209 | dlChooser.addActionListener(this);
|
---|
| 210 | dlPanel.setBorder(BorderFactory.createTitledBorder(
|
---|
| 211 | "Digital library settings"));
|
---|
| 212 |
|
---|
| 213 | this.proxyhostField = new JTextField(15);
|
---|
| 214 | this.proxyportField = new JTextField(4);
|
---|
| 215 | this.nonProxyHostNamesField = new JTextField(20);
|
---|
| 216 | this.setProxySettings = new JButton("Set");
|
---|
| 217 | nonProxyHostNamesField.setToolTipText("The hosts for which no proxies are required "
|
---|
| 218 | + "(separate hosts with |, * wildcard allowed)");
|
---|
| 219 | JPanel topProxyPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
---|
| 220 | topProxyPanel.add(new JLabel("Proxy host:"));
|
---|
| 221 | topProxyPanel.add(proxyhostField);
|
---|
| 222 | topProxyPanel.add(new JLabel("Proxy port:"));
|
---|
| 223 | topProxyPanel.add(proxyportField);
|
---|
| 224 | JPanel bottomProxyPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
---|
| 225 | bottomProxyPanel.add(new JLabel("No proxy for:"));
|
---|
| 226 | bottomProxyPanel.add(nonProxyHostNamesField);
|
---|
| 227 | bottomProxyPanel.add(setProxySettings);
|
---|
| 228 | setProxySettings.addActionListener(this);
|
---|
| 229 | JPanel proxyPanel = new JPanel(new BorderLayout());
|
---|
| 230 | proxyPanel.add(topProxyPanel, BorderLayout.CENTER);
|
---|
| 231 | proxyPanel.add(bottomProxyPanel, BorderLayout.SOUTH);
|
---|
| 232 | proxyPanel.setBorder(BorderFactory.createTitledBorder(
|
---|
| 233 | "Connection settings"));
|
---|
| 234 |
|
---|
| 235 | // Add the dlPanel and proxyPanel next to each other at the top
|
---|
| 236 | JPanel topPanel = new JPanel(new BorderLayout());
|
---|
| 237 | topPanel.add(dlPanel, BorderLayout.CENTER);
|
---|
| 238 | topPanel.add(proxyPanel, BorderLayout.EAST);
|
---|
| 239 |
|
---|
| 240 | // Setting up the GUI of this client
|
---|
| 241 | // create a JComboBox, and an item in it for each collection
|
---|
| 242 | collBox = new JComboBox();
|
---|
| 243 | serviceBox = new JComboBox();
|
---|
| 244 |
|
---|
| 245 | JPanel collPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
---|
| 246 | collPanel.add(new JLabel("Choose collection:"));
|
---|
| 247 | collPanel.add(collBox);
|
---|
| 248 | // displayName
|
---|
| 249 | collPanel.add(new JLabel("Full name:"));
|
---|
| 250 | collectionNameField = new JTextField(18);
|
---|
| 251 | collectionNameField.setEditable(false);
|
---|
| 252 | collectionNameField.setCaretPosition(0);
|
---|
| 253 | collPanel.add(collectionNameField);
|
---|
| 254 | // detailed information button, shows collection's description
|
---|
| 255 | collInfoButton = new JButton("Info");
|
---|
| 256 | collInfoButton.addActionListener(this);
|
---|
| 257 | collPanel.add(collInfoButton);
|
---|
| 258 |
|
---|
| 259 | JPanel servicePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
---|
| 260 | servicePanel.add(new JLabel("Available services:"));
|
---|
| 261 | servicePanel.add(serviceBox);
|
---|
| 262 |
|
---|
| 263 | JPanel collServicesPanel = new JPanel(new BorderLayout());
|
---|
| 264 | collServicesPanel.add(collPanel, BorderLayout.NORTH);
|
---|
| 265 | collServicesPanel.add(servicePanel, BorderLayout.SOUTH);
|
---|
| 266 |
|
---|
| 267 | tabbedPane = new JTabbedPane(); // tabs on top
|
---|
| 268 | queryPanel = new QueryForm(this);
|
---|
| 269 | tabbedPane.add("Query", queryPanel);
|
---|
| 270 | searchResultsDisplay = new SearchResultsDisplay(this);
|
---|
| 271 | searchResultsDisplay.setOpaque(true); //necessary for JTree
|
---|
| 272 |
|
---|
| 273 | JScrollPane searchView = new JScrollPane(searchResultsDisplay);
|
---|
| 274 | searchSummary = new JTextArea();
|
---|
| 275 | searchSummary.setEditable(false);
|
---|
| 276 |
|
---|
| 277 | searchPanel = new JPanel(new BorderLayout());
|
---|
| 278 | searchPanel.add(searchView, BorderLayout.CENTER);
|
---|
| 279 | searchPanel.add(searchSummary, BorderLayout.NORTH);
|
---|
| 280 | tabbedPane.add("Search Results", searchPanel);
|
---|
| 281 |
|
---|
| 282 | JPanel activityPanel = new JPanel(new BorderLayout());
|
---|
| 283 | activityPanel.add(collServicesPanel, BorderLayout.NORTH);
|
---|
| 284 | activityPanel.add(tabbedPane, BorderLayout.CENTER);
|
---|
| 285 |
|
---|
| 286 | Container c = this.getContentPane();
|
---|
| 287 | c.setLayout(new BorderLayout()); // new BoxLayout(c, BoxLayout.Y_AXIS));
|
---|
| 288 | c.add(topPanel, BorderLayout.NORTH);
|
---|
| 289 | c.add(activityPanel, BorderLayout.CENTER);
|
---|
| 290 |
|
---|
| 291 | // browse panel
|
---|
| 292 | browsePanel = new BrowseDisplay(this);
|
---|
| 293 | tabbedPane.add("Browse", browsePanel);
|
---|
| 294 |
|
---|
| 295 | // add actionlisteners
|
---|
| 296 | collBox.addActionListener(this);
|
---|
| 297 | serviceBox.addActionListener(this);
|
---|
| 298 |
|
---|
| 299 | // GUI DONE, now instantiate the DATA and DIGITAL LIBRARY objects
|
---|
| 300 | // instantiate the objects that deal with storing query response data
|
---|
| 301 | // and browse response data
|
---|
| 302 | queryResponseObj = new QueryResponseData();
|
---|
| 303 | browseResponseObject = new BrowseResponseData();
|
---|
| 304 |
|
---|
| 305 | // The java.net.Authenticator can be used to send user credentials
|
---|
| 306 | // when needed. When no username/password are provided then a popup
|
---|
| 307 | // is shown to ask for the credentials. *Only* when a site/realm
|
---|
| 308 | // requires password and username does the Authenticator show the
|
---|
| 309 | // dialog. For example, the dialog will appear when pwd & username
|
---|
| 310 | // are needed for proxy authorisation.
|
---|
| 311 | Authenticator.setDefault(new PasswordAuthenticator());
|
---|
| 312 |
|
---|
| 313 | changeDL(null); // no dl selected
|
---|
| 314 |
|
---|
| 315 | // Set the selection colours that will be uniform for all DLs
|
---|
| 316 | UIManager.put("Tree.textBackground", ColourCombo.transparent);
|
---|
| 317 | // Instead of the white tree text background, set it to transparent
|
---|
| 318 | UIManager.put("Tree.selectionBackground", ColourCombo.yellow);
|
---|
| 319 | UIManager.put("TabbedPane.selected", ColourCombo.yellow);
|
---|
| 320 | UIManager.put("TabbedPane.selected", ColourCombo.yellow);
|
---|
| 321 | UIManager.put("ComboBox.selectionBackground", ColourCombo.yellow);
|
---|
| 322 | UIManager.put("List.selectionBackground", ColourCombo.yellow);
|
---|
| 323 | UIManager.put("TextArea.selectionBackground", ColourCombo.yellow);
|
---|
| 324 | UIManager.put("TextField.selectionBackground", ColourCombo.yellow);
|
---|
| 325 | // force the UI to load these new UIManager defaults
|
---|
| 326 | javax.swing.SwingUtilities.updateComponentTreeUI(this);
|
---|
| 327 | // We can't change the UIManager defaults (properly) throughout GUI
|
---|
| 328 | // display-time, only upon creation and first display. This is
|
---|
| 329 | // because updateComponentTreeUI() has no effect once components
|
---|
| 330 | // have been displayed. For this reason, the various changeUIColor()
|
---|
| 331 | // methods and class ColourCombo have been written.
|
---|
| 332 | }
|
---|
| 333 |
|
---|
| 334 | /** Attempts to establish a connection to GS3 Web services and instantiate
|
---|
| 335 | * a GS3ServicesAPIA object and store it in the member variable greenstoneDL.
|
---|
| 336 | * If it was unsuccessful, then this variable remains at null and an error
|
---|
| 337 | * message is displayed. */
|
---|
| 338 | protected boolean createGreenstoneDLConnection()
|
---|
| 339 | {
|
---|
| 340 | // store the old choice of dl, if there was any
|
---|
| 341 | int oldSetting = (dlAPIA == null) ? SELECT : FEDORA;
|
---|
| 342 | // try instantiating a GS3 dl handle
|
---|
| 343 | try {
|
---|
| 344 | greenstoneDL = new GS3ServicesAPIA();
|
---|
| 345 | return true; // success
|
---|
| 346 | } catch(DigitalLibraryServicesAPIA.CancelException e){
|
---|
| 347 | // The user pressed cancel in the gs3 services instantiation dialog
|
---|
| 348 | // Set the dl drop-down list option back to whatever it was
|
---|
| 349 | } catch(Exception e) {
|
---|
| 350 | // still unable to instantiate greenstone, but show
|
---|
| 351 | // the error for what went wrong
|
---|
| 352 | JOptionPane.showMessageDialog(
|
---|
| 353 | null,
|
---|
[15377] | 354 | "Error connecting to Greenstone 3 QBRSOAPServer web services.\n"
|
---|
[15378] | 355 | + "When attempting to process its wsdl file, encountered the problem:\n"
|
---|
[15222] | 356 | + e,
|
---|
[15377] | 357 | "Fatal error instantiating Digital Library Services interface. Exiting...",
|
---|
[15222] | 358 | JOptionPane.ERROR_MESSAGE
|
---|
| 359 | );
|
---|
| 360 | //e.printStackTrace(System.err);
|
---|
| 361 | LOG.error("Error connecting to Greenstone 3 web services:\n" + e);
|
---|
| 362 | }
|
---|
| 363 | // We'd be here if an exception occurred. Need to back to the old dl
|
---|
| 364 | // settings
|
---|
| 365 | dlChooser.setSelectedIndex(oldSetting);
|
---|
| 366 | return false;
|
---|
| 367 | }
|
---|
| 368 |
|
---|
| 369 | /** Attempts to establish a connection to FedoraGS3.jar and instantiate
|
---|
| 370 | * a FedoraServicesAPIA object and store it in the member variable fedoraDL.
|
---|
| 371 | * If it was unsuccessful, then this variable remains at null and an error
|
---|
| 372 | * message is displayed. */
|
---|
| 373 | protected boolean createFedoraDLConnection()
|
---|
| 374 | {
|
---|
| 375 | // store the old choice of dl, if there was any
|
---|
| 376 | int oldSetting = oldSetting = (dlAPIA == null) ? SELECT : GREENSTONE;
|
---|
| 377 | // Try to instantiate a Fedora dl handle
|
---|
| 378 | try {
|
---|
| 379 | fedoraDL = new FedoraServicesAPIA();
|
---|
| 380 | return true; // success
|
---|
| 381 | } catch(
|
---|
| 382 | org.greenstone.fedora.services.FedoraGS3Exception.CancelledException e)
|
---|
| 383 | {
|
---|
| 384 | // The user pressed cancel in the fedora services instantiation dlg
|
---|
| 385 | // Set the dl drop-down list option back to whatever it was
|
---|
| 386 | } catch(Exception e) {
|
---|
| 387 | JOptionPane.showMessageDialog(
|
---|
| 388 | null,
|
---|
| 389 | "Error instantiating the interface to the Fedora Repository\n"+ e,
|
---|
| 390 | "Unable to connect to Fedora's digital library services.",
|
---|
| 391 | JOptionPane.ERROR_MESSAGE
|
---|
| 392 | );
|
---|
| 393 | //e.printStackTrace(System.err);
|
---|
| 394 | LOG.error(
|
---|
| 395 | "Error instantiating the interface to the Fedora Repository:\n"+ e);
|
---|
| 396 | }
|
---|
| 397 | // We'd be here if an exception occurred. Need to go back to the old dl
|
---|
| 398 | // settings
|
---|
| 399 | dlChooser.setSelectedIndex(oldSetting);
|
---|
| 400 | return false;
|
---|
| 401 | }
|
---|
| 402 |
|
---|
| 403 | /** Method that is called when the user chooses to change the active
|
---|
| 404 | * digital library (between Greenstone3 and Fedora).
|
---|
| 405 | * @param dl is the new active digital library (the
|
---|
| 406 | * DigitalLibraryServicesAPIA object to change to). */
|
---|
| 407 | protected void changeDL(DigitalLibraryServicesAPIA dl) {
|
---|
| 408 | // change the colour of the interface
|
---|
| 409 | this.changeUIColour(dlChooser.getSelectedIndex());
|
---|
| 410 |
|
---|
| 411 | // clear up remnants of previously selected digital library's
|
---|
| 412 | // processing
|
---|
| 413 | browsePanel.clear();
|
---|
| 414 | searchResultsDisplay.clear();
|
---|
| 415 | this.searchSummary.setText("");
|
---|
| 416 | browseResponseObject.clear();
|
---|
| 417 | queryResponseObj.clear();
|
---|
| 418 |
|
---|
| 419 | // set current digital library to selected one
|
---|
| 420 | dlAPIA = dl;
|
---|
| 421 |
|
---|
| 422 | if(dlAPIA == null) {
|
---|
| 423 | // clear some panels so the user can't do anything
|
---|
| 424 | this.queryPanel.clear();
|
---|
| 425 | collBox.removeAllItems();
|
---|
| 426 | collBox.setEnabled(false);
|
---|
| 427 | serviceBox.removeAllItems();
|
---|
| 428 | serviceBox.setEnabled(false);
|
---|
| 429 | this.collectionNameField.setText("");
|
---|
| 430 | this.collInfoButton.setEnabled(false);
|
---|
| 431 | return;
|
---|
| 432 | }
|
---|
| 433 |
|
---|
| 434 | // start retrieving the information related to the chosen dl
|
---|
| 435 | String response = dlAPIA.describe();
|
---|
| 436 | if(response == null) {
|
---|
| 437 | LOG.error("Error: no response from dlAPIA.describe() of "
|
---|
| 438 | + dlAPIA.getDisplayName());
|
---|
| 439 | System.exit(1);
|
---|
| 440 | }
|
---|
| 441 |
|
---|
| 442 | Element responseXML = getResponseAsDOM(
|
---|
| 443 | "DESCRIBE RESPONSE:\n", response);
|
---|
| 444 |
|
---|
| 445 | // Get the collectionList element of the response
|
---|
| 446 | // from the default messageRouter-describe:
|
---|
| 447 | Element collectionList = ParseUtil.getFirstDescElementCalled(
|
---|
| 448 | responseXML, // (<message>, "collectionList")
|
---|
| 449 | GSXML.COLLECTION_ELEM+GSXML.LIST_MODIFIER
|
---|
| 450 | );
|
---|
| 451 | if(collectionList == null)
|
---|
| 452 | LOG.error("collectionList is null!");
|
---|
| 453 |
|
---|
| 454 | // Next, create a CollectionData object for each collection using
|
---|
| 455 | // its name
|
---|
| 456 | CollectionData[] collData = null;
|
---|
| 457 | Vector v = ParseUtil.getAllChildElementsCalled(collectionList,
|
---|
| 458 | GSXML.COLLECTION_ELEM); // (<collectionList>, "collection")
|
---|
| 459 | if(v == null)
|
---|
| 460 | LOG.error("collections are null!");
|
---|
| 461 |
|
---|
| 462 | if(v != null) {
|
---|
| 463 | StringBuffer buf = new StringBuffer("Collections:\n");
|
---|
| 464 | collData = new CollectionData[v.size()];
|
---|
| 465 | for(int i = 0; i < v.size(); i++){
|
---|
| 466 | collData[i] = new CollectionData((Element)v.get(i));
|
---|
| 467 | buf.append(collData[i].name + ", ");
|
---|
| 468 | }
|
---|
| 469 | }
|
---|
| 470 |
|
---|
| 471 | // Now send a describe request to each collection
|
---|
| 472 | // And set the fields for each collData using the response
|
---|
| 473 | for(int i = 0; i < collData.length; i++){
|
---|
| 474 | response = dlAPIA.describeCollection(collData[i].name);
|
---|
| 475 | responseXML = getResponseAsDOM(
|
---|
| 476 | "describeCollection "+collData[i].name+":", response);
|
---|
| 477 | Element collectionTag = ParseUtil.getFirstDescElementCalled(
|
---|
| 478 | responseXML, GSXML.COLLECTION_ELEM);
|
---|
| 479 |
|
---|
| 480 | // set the other fields of the CollectionData object using
|
---|
| 481 | // the collectionTag of the response from Collection-describe:
|
---|
| 482 | collData[i].setFields(collectionTag);
|
---|
| 483 | }
|
---|
| 484 |
|
---|
| 485 | if(collData == null) {
|
---|
| 486 | LOG.debug("No collections in the chosen repository");
|
---|
| 487 | return;
|
---|
| 488 | } else {
|
---|
| 489 | this.collInfoButton.setEnabled(true);
|
---|
| 490 | collBox.setEnabled(true);
|
---|
| 491 | serviceBox.setEnabled(true);
|
---|
| 492 | }
|
---|
| 493 |
|
---|
| 494 | // fill in the combobox containing the collections and the one
|
---|
| 495 | // containing the services
|
---|
| 496 | collBox.removeAllItems();
|
---|
| 497 | for(int i = 0; i < collData.length; i++)
|
---|
| 498 | collBox.addItem(collData[i]);
|
---|
| 499 | collBox.setSelectedItem(collData[0]);
|
---|
| 500 |
|
---|
| 501 | this.serviceBox.removeAllItems();
|
---|
| 502 | ServiceData[] serviceData = collData[0].getServiceList(
|
---|
| 503 | executableServicesOnly);
|
---|
| 504 | for(int i = 0; i < serviceData.length; i++)
|
---|
| 505 | serviceBox.addItem(serviceData[i]);
|
---|
| 506 | serviceBox.setSelectedIndex(0); // whichever might be the first
|
---|
| 507 | }
|
---|
| 508 |
|
---|
| 509 | /** Given an XML response string, returns the root document (element)
|
---|
| 510 | * representing its DOM form.
|
---|
| 511 | * @param response - the XML response string to be converted into
|
---|
| 512 | * its DOM form
|
---|
| 513 | * @return the response as an XML DOM Element */
|
---|
| 514 | protected Element getResponseAsDOM(String debugPrefix, String response) {
|
---|
| 515 | if(response == null) // will not be the case, because an empty
|
---|
| 516 | return null; // response message will be sent instead
|
---|
| 517 |
|
---|
| 518 | // First let's print out the response to the LOG
|
---|
| 519 | // Note that the response is XML and will start on new line already
|
---|
[15673] | 520 | LOG.debug(debugPrefix + "\n" + response);
|
---|
[15222] | 521 | // The following line when uncommented will output all response
|
---|
| 522 | // msgs coming back from the web services
|
---|
[15673] | 523 | //System.out.println(debugPrefix + "\n" + response);
|
---|
[15222] | 524 |
|
---|
| 525 | // At present, assuming response is okay - later need to first look
|
---|
| 526 | // for element <error> and process this meaningfully before returning
|
---|
| 527 | // XML DOM version of response. Example error:
|
---|
| 528 | // <message>
|
---|
| 529 | // <response from="infomine/TextQuery" type="process">
|
---|
| 530 | // <documentNodeList />
|
---|
| 531 | // <error type="other">IOException during connection to http://infominehelper.ucr.edu/cgi-bin/canned_search?theme=gsdl3&query=water&fields=kw,au,su,ti,de,fu,&no_of_records_per_page=10&start_page_no=1: java.net.ConnectException: Connection refused</error>
|
---|
| 532 | // </response>
|
---|
| 533 | // </message>
|
---|
| 534 |
|
---|
| 535 | Element message = null;
|
---|
| 536 | try{
|
---|
| 537 | // turn the String xml response into a DOM tree:
|
---|
| 538 | DocumentBuilder builder
|
---|
| 539 | = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
---|
| 540 | Document doc
|
---|
| 541 | = builder.parse(new InputSource(new StringReader(response)));
|
---|
| 542 | message = doc.getDocumentElement();
|
---|
| 543 | } catch(Exception e){
|
---|
| 544 | if(response == null) {
|
---|
| 545 | response = "";
|
---|
| 546 | }
|
---|
| 547 | JOptionPane.showMessageDialog(this,
|
---|
| 548 | "An error occurred while trying to parse the response:\n"
|
---|
| 549 | + response
|
---|
| 550 | + "\nException message:\n" + e.getMessage(),
|
---|
| 551 | "Parse error", JOptionPane.ERROR_MESSAGE);
|
---|
| 552 | e.printStackTrace();
|
---|
| 553 | }
|
---|
| 554 |
|
---|
| 555 | NodeList errorList = message.getElementsByTagName(GSXML.ERROR_ELEM);
|
---|
| 556 | if(errorList.getLength() == 0)
|
---|
| 557 | return message;
|
---|
| 558 |
|
---|
| 559 | // else we have one (or more?) error(s):
|
---|
| 560 | Element error = (Element)errorList.item(0);
|
---|
| 561 | String errorMessage = ParseUtil.getBodyTextValue(error);
|
---|
| 562 | String errorType = error.getAttribute("type");
|
---|
| 563 |
|
---|
| 564 | // no need to display error message if it was a query that was
|
---|
| 565 | // just executed and no results were found
|
---|
| 566 | if(//errorType.equals(GSXML.ERROR_TYPE_SYNTAX) &&
|
---|
| 567 | errorMessage.toLowerCase().indexOf("no documentnode found") != -1)
|
---|
| 568 | {
|
---|
| 569 | // if we're in here, we know that a search/query was performed
|
---|
| 570 | // That means we are dealing with the searchResultsDisplay
|
---|
| 571 | // and can clear it.
|
---|
| 572 | this.searchResultsDisplay.clear();
|
---|
| 573 | this.searchSummary.setText("");
|
---|
| 574 | }
|
---|
| 575 | else { // display error message
|
---|
[15440] | 576 | final int numLetters = 60; // number of letters per line
|
---|
[15222] | 577 | String[] words = errorMessage.split(" "); //get the individual words
|
---|
| 578 | String line = words[0];
|
---|
| 579 | errorMessage = "";
|
---|
| 580 | // go through all the words and build up lines where none is
|
---|
| 581 | // longer than the specified number of letters
|
---|
| 582 | for(int i = 1; i < words.length; i++) { // append the word
|
---|
| 583 | // and a space to the same line unless the line is too long
|
---|
| 584 | if(numLetters > line.length() + words[i].length()) {
|
---|
| 585 | if(line.equals(""))
|
---|
| 586 | line = words[i];
|
---|
| 587 | else line = line + " " + words[i];
|
---|
| 588 |
|
---|
| 589 | // check if line is full after adding new word
|
---|
| 590 | if(line.length() == numLetters) { // finish the line
|
---|
| 591 | errorMessage = errorMessage + line + "\n";
|
---|
| 592 | line = "";
|
---|
| 593 | }
|
---|
| 594 | } // else the word has to go on the next line
|
---|
| 595 | else { //finish the line and move on:
|
---|
| 596 | errorMessage = errorMessage + line + "\n";
|
---|
[15440] | 597 | line = words[i];
|
---|
[15222] | 598 | }
|
---|
[15440] | 599 | if(i == (words.length-1)) { // extra word on last line
|
---|
| 600 | errorMessage = errorMessage + line;
|
---|
| 601 | }
|
---|
[15222] | 602 | }
|
---|
| 603 | LOG.debug("errorMessage:\n" + errorMessage);
|
---|
| 604 | JOptionPane.showMessageDialog(this, errorMessage, "Error: "+errorType,
|
---|
| 605 | JOptionPane.ERROR_MESSAGE);
|
---|
| 606 | }
|
---|
| 607 | return message;
|
---|
| 608 | }
|
---|
| 609 |
|
---|
| 610 | /** Event handler for actionEvents such as a change in the active digital
|
---|
| 611 | * library, a collection being selected in the dropdown box or the collection
|
---|
| 612 | * -Info button being pressed, or a service being selected in the service
|
---|
| 613 | * dropdown box (browsing or searching). */
|
---|
| 614 | public void actionPerformed(ActionEvent e) {
|
---|
| 615 | if(e.getSource() == dlChooser) {
|
---|
| 616 | // We need to change to a Wait cursor while we do the switch
|
---|
| 617 | Container c = this.getContentPane();
|
---|
| 618 | c.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
---|
| 619 |
|
---|
| 620 | boolean success = true;
|
---|
| 621 | // Change the dlAPIA handle to the chosen digital library,
|
---|
| 622 | // instantiating DigitalLibraryServicesAPIA objects when necessary:
|
---|
| 623 | // if they haven't yet been created
|
---|
| 624 | switch(dlChooser.getSelectedIndex())
|
---|
| 625 | {
|
---|
| 626 | case GREENSTONE:
|
---|
| 627 | if(this.greenstoneDL == null) {
|
---|
| 628 | success = createGreenstoneDLConnection();
|
---|
| 629 | }
|
---|
| 630 | // no need to do anything if the user chose
|
---|
| 631 | // the same DL again
|
---|
| 632 | if(success && dlAPIA!=this.greenstoneDL) {
|
---|
| 633 | // current DL not already set to greenstoneDL
|
---|
| 634 | // so set it
|
---|
| 635 | this.changeDL(greenstoneDL);
|
---|
| 636 | }
|
---|
| 637 | break;
|
---|
| 638 | case FEDORA:
|
---|
| 639 | if(this.fedoraDL == null) {
|
---|
| 640 | success = createFedoraDLConnection();
|
---|
| 641 | }
|
---|
| 642 | // no need to do anything if the user chose
|
---|
| 643 | // the same DL again
|
---|
| 644 | if(success && dlAPIA!=this.fedoraDL) {
|
---|
| 645 | // current DL not already set to fedoraDL
|
---|
| 646 | // so set it
|
---|
| 647 | this.changeDL(fedoraDL);
|
---|
| 648 | }
|
---|
| 649 | break;
|
---|
| 650 | case SELECT:
|
---|
| 651 | default:
|
---|
| 652 | this.changeDL(null); // no dl, so default colours
|
---|
| 653 | break;
|
---|
| 654 | }
|
---|
| 655 | // set the cursor back
|
---|
| 656 | c.setCursor(Cursor.getDefaultCursor());
|
---|
| 657 | } else if(e.getSource() == collBox) {
|
---|
| 658 | CollectionData collDataEl
|
---|
| 659 | = (CollectionData)collBox.getSelectedItem();
|
---|
| 660 |
|
---|
| 661 | if(collDataEl == null) // need to check for this here, because
|
---|
| 662 | return; // removing all items from collBox fires actionPerformed
|
---|
| 663 |
|
---|
| 664 | // display the collection's full name
|
---|
| 665 | this.collectionNameField.setText(collDataEl.getDisplayName());
|
---|
| 666 | this.collectionNameField.setCaretPosition(0);
|
---|
| 667 |
|
---|
| 668 | // display the services in the selected collection
|
---|
| 669 | serviceBox.removeAllItems();
|
---|
| 670 | ServiceData[] servicelist = collDataEl.getServiceList(
|
---|
| 671 | executableServicesOnly);
|
---|
| 672 | for(int i = 0; i < servicelist.length; i++)
|
---|
| 673 | serviceBox.addItem(servicelist[i]);
|
---|
| 674 |
|
---|
| 675 | } else if(e.getSource() == serviceBox) {
|
---|
| 676 | ServiceData selService = (ServiceData)serviceBox.getSelectedItem();
|
---|
| 677 | if(selService == null || selService.type == null)
|
---|
| 678 | return; // nothing valid chosen
|
---|
| 679 |
|
---|
| 680 | if(selService.type.equals(GSXML.SERVICE_TYPE_QUERY)) {
|
---|
| 681 | // Make sure we can't accidentally work with already deallocated
|
---|
| 682 | // data objects in the browsePanel
|
---|
| 683 | browsePanel.clear();
|
---|
| 684 | searchSummary.setText(""); // empty any text in the search summary
|
---|
| 685 |
|
---|
| 686 | this.activity = SEARCHING; // ensures the components are
|
---|
| 687 | // displayed and shown again, whereas a call to repaint()
|
---|
| 688 | // did not do the trick
|
---|
| 689 |
|
---|
| 690 | tabbedPane.setSelectedComponent(this.queryPanel);
|
---|
| 691 |
|
---|
| 692 | // send off a describe request to the service
|
---|
| 693 | // in that collection
|
---|
| 694 | CollectionData selColl
|
---|
| 695 | = (CollectionData)collBox.getSelectedItem();
|
---|
| 696 | colName = selColl.name;
|
---|
| 697 | serviceName = selService.name;
|
---|
| 698 |
|
---|
| 699 | String response = dlAPIA.describeCollectionService(
|
---|
| 700 | colName, serviceName);
|
---|
[26174] | 701 |
|
---|
[15222] | 702 | Element serviceResponseXML = getResponseAsDOM(
|
---|
| 703 | "DescribeCollectionService "+colName+"/"+serviceName,
|
---|
| 704 | response);
|
---|
| 705 |
|
---|
| 706 | // generate the appropriate query form as per how the
|
---|
| 707 | // query has described itself
|
---|
| 708 | queryPanel.formFromQueryServiceDescribe(serviceResponseXML);
|
---|
| 709 | } else if(selService.type.equals(GSXML.SERVICE_TYPE_BROWSE)) {
|
---|
| 710 | LOG.debug("Browse option chosen");
|
---|
| 711 | this.searchResultsDisplay.clear();
|
---|
| 712 | this.searchSummary.setText("");
|
---|
| 713 | this.queryPanel.clear(); // can't do any searching either
|
---|
| 714 | this.activity = BROWSING;
|
---|
| 715 | tabbedPane.setSelectedComponent(this.browsePanel);
|
---|
| 716 |
|
---|
| 717 | CollectionData selColl
|
---|
| 718 | = (CollectionData)collBox.getSelectedItem();
|
---|
| 719 | colName = selColl.name;
|
---|
| 720 | serviceName = selService.name;
|
---|
| 721 |
|
---|
| 722 | // first send a request for the browse service's metadata
|
---|
| 723 | // see manual pp.37 and 48
|
---|
| 724 | String response = dlAPIA.describeCollectionService(
|
---|
| 725 | colName, serviceName);
|
---|
| 726 | Element responseMsg = getResponseAsDOM(
|
---|
| 727 | colName+"/"+serviceName+":", response);
|
---|
| 728 | browsePanel.displayBrowseOptions(responseMsg);
|
---|
| 729 | } else { // clicked on non-query, non-browse option, remove form
|
---|
| 730 | queryPanel.clear();
|
---|
| 731 | }
|
---|
| 732 | } else if(e.getSource() == collInfoButton){
|
---|
| 733 | CollectionData collDataEl
|
---|
| 734 | = (CollectionData)collBox.getSelectedItem();
|
---|
| 735 |
|
---|
| 736 | // Create the HTML viewing pane.
|
---|
| 737 | JEditorPane information = new JEditorPane();
|
---|
| 738 | information.setEditable(false);
|
---|
[21835] | 739 | information.setContentType("text/html");
|
---|
[15222] | 740 | information.setText(collDataEl.info());
|
---|
| 741 |
|
---|
| 742 | // Display the dialog with the information in a scrollpane
|
---|
| 743 | JDialog dialog = new JDialog(this, collDataEl.toString());
|
---|
| 744 | dialog.getContentPane().add(new JScrollPane(information));
|
---|
| 745 | dialog.setDefaultCloseOperation(DISPOSE_ON_CLOSE); // not EXIT!
|
---|
| 746 | dialog.pack();
|
---|
| 747 | dialog.setSize(400, 300);
|
---|
| 748 | dialog.setVisible(true);
|
---|
| 749 | }
|
---|
| 750 | else if(e.getSource() == setProxySettings) { // proxy settings button
|
---|
| 751 | // Sthe proxy settings as given in the fields
|
---|
| 752 | String proxyHost = this.proxyhostField.getText();
|
---|
| 753 | String proxyPort = this.proxyportField.getText();
|
---|
| 754 | if(proxyHost.equals("") && proxyPort.equals("")) {
|
---|
| 755 | return;
|
---|
| 756 | } else {
|
---|
| 757 | // Handle proxy settings
|
---|
| 758 | // (don't need to write to propertiesFile, since proxy
|
---|
| 759 | // settings are System properties)
|
---|
| 760 | java.util.Properties systemSettings = System.getProperties();
|
---|
| 761 | systemSettings.put("http.proxyHost", proxyHost);
|
---|
| 762 | systemSettings.put("http.proxyPort", proxyPort);
|
---|
| 763 | // give the hosts for which no proxies are required:
|
---|
| 764 | systemSettings.put("http.nonProxyHosts",
|
---|
| 765 | this.nonProxyHostNamesField.getText());
|
---|
| 766 | System.setProperties(systemSettings);
|
---|
| 767 | }
|
---|
| 768 | }
|
---|
| 769 | }
|
---|
| 770 |
|
---|
| 771 | /** Called by the instance of the QueryForm class when the user has
|
---|
| 772 | * pressed the queryPanel's search button to execute a query. Based on
|
---|
| 773 | * the user-entered values (stored in the parameter HashMap) this
|
---|
| 774 | * method will call Greenstone to process the query.
|
---|
| 775 | * @param nameValParamsMap - the query form control names with the values
|
---|
| 776 | * the user has entered for them. Example, the pair (fqv, the query string),
|
---|
| 777 | * where fqv is the form control name for the query term. */
|
---|
| 778 | public void performSearch(HashMap nameValParamsMap) {
|
---|
| 779 | //Container c = this.getContentPane();
|
---|
| 780 | //c.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
---|
| 781 | this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
---|
| 782 |
|
---|
| 783 | // (1) Now let's process this query request - passing the
|
---|
| 784 | // currently selected collection and service:
|
---|
| 785 | String responseXML = dlAPIA.query(
|
---|
| 786 | colName, serviceName, nameValParamsMap);
|
---|
| 787 |
|
---|
| 788 | // (2) The search results: document identifiers are returned,
|
---|
| 789 | // use these to construct a QueryResponseData object
|
---|
| 790 | Element responseMessage
|
---|
| 791 | = getResponseAsDOM("Search response:", responseXML);
|
---|
| 792 | queryResponseObj.setResponseData(responseMessage);
|
---|
| 793 | LOG.debug(queryResponseObj);
|
---|
| 794 |
|
---|
| 795 | DocumentNodeData[] doclist = queryResponseObj.getDocumentNodeList();
|
---|
| 796 |
|
---|
| 797 | // (3) To retrieve Title metadata, need to call with "Title"!!!!
|
---|
| 798 | // (1st letter in caps)
|
---|
| 799 | // Retrieving just metadata name=Title for ALL docs (=all docIDs)
|
---|
| 800 | String metaResponseXML = dlAPIA.retrieveTitleMetadata(this.colName,
|
---|
| 801 | queryResponseObj.getDocumentNodeIDs());
|
---|
| 802 | Element metaResponse
|
---|
| 803 | = getResponseAsDOM("Meta response:", metaResponseXML);
|
---|
| 804 | queryResponseObj.setMetadataForDocuments(metaResponse);
|
---|
| 805 |
|
---|
| 806 | // doclist should now have been updated with title metadata for
|
---|
| 807 | // each doc (docNode)
|
---|
| 808 | //for(int i = 0; i < doclist.length; i++)
|
---|
| 809 | //LOG.debug(doclist[i].show());
|
---|
| 810 |
|
---|
| 811 | // (4) Display this in the search results TreeView
|
---|
| 812 | tabbedPane.setSelectedComponent(searchPanel);
|
---|
| 813 | searchResultsDisplay.setResults(doclist);
|
---|
| 814 | searchSummary.setText(queryResponseObj.toString());
|
---|
| 815 | searchResultsDisplay.validate();
|
---|
| 816 | this.searchPanel.validate();
|
---|
| 817 | this.searchPanel.repaint();
|
---|
| 818 |
|
---|
| 819 | // set the cursor back
|
---|
| 820 | //c.setCursor(Cursor.getDefaultCursor());
|
---|
| 821 | this.setCursor(Cursor.getDefaultCursor());
|
---|
| 822 | }
|
---|
| 823 |
|
---|
| 824 |
|
---|
| 825 | /* SEARCH RELATED METHODS */
|
---|
| 826 | /** Performs a docMetadataRetrieve message request for the docNode
|
---|
| 827 | * iff the metadata for that docNode is not already set.
|
---|
| 828 | * @param docNode is the DocumentNodeData object for which all the
|
---|
| 829 | * metadata is to be retrieved. */
|
---|
| 830 | public void retrieveAllMetadataFor(DocumentNodeData docNode) {
|
---|
| 831 | // Lazy retrieval: only retrieve metadata of docNode when required
|
---|
| 832 | // and if metadata not already set
|
---|
| 833 | if(docNode.getMetadataList() == null
|
---|
| 834 | || docNode.getMetadataList().size() <= 1)
|
---|
| 835 | { // not set yet or only title set,
|
---|
| 836 | // so do a docMetadataRetrieve for the docNode (all
|
---|
| 837 | // metadata fields retrieved):
|
---|
| 838 | String metaResponseXML = dlAPIA.retrieveDocumentMetadata(
|
---|
[22299] | 839 | this.colName, new String[] { docNode.nodeID }, new String[] {"all"});
|
---|
[15222] | 840 | Element metaResponse
|
---|
| 841 | = getResponseAsDOM("Meta response", metaResponseXML);
|
---|
| 842 |
|
---|
| 843 | // Set the metadata for the docNode
|
---|
| 844 | if(this.activity == SEARCHING)
|
---|
| 845 | queryResponseObj.setMetadataForDocuments(metaResponse);
|
---|
| 846 | else if(this.activity == BROWSING)
|
---|
| 847 | browseResponseObject.setMetadataForDocuments(metaResponse);
|
---|
| 848 | } //else docNode's list of metadata already set
|
---|
| 849 | }
|
---|
| 850 |
|
---|
| 851 | /** Performs a docMetadataRetrieve message request for the docNode
|
---|
| 852 | * iff the nodeContent for that docNode is not already set.
|
---|
| 853 | * @param docNode is the DocumentNodeData object for which the content
|
---|
| 854 | * is to be retrieved. */
|
---|
| 855 | public void retrieveContentFor(DocumentNodeData docNode) {
|
---|
| 856 | // Lazy retrieval: only retrieve content when required.
|
---|
| 857 | // If it is not yet set, then we do the retrieval, else
|
---|
| 858 | // our work here is done
|
---|
| 859 | if(docNode.getContent() == null) { // not set yet, so
|
---|
| 860 | // retrieve the content for the docNode
|
---|
| 861 | String contentResponseXML = dlAPIA.retrieveDocumentContent(
|
---|
| 862 | this.colName, new String[] { docNode.nodeID });
|
---|
| 863 | Element contentResponse = getResponseAsDOM(
|
---|
| 864 | "Content response:", contentResponseXML);
|
---|
| 865 | // probably when infomine is down
|
---|
| 866 | // Set the content for the docNode
|
---|
| 867 | if(this.activity==SEARCHING)
|
---|
| 868 | queryResponseObj.setContentForDocs(contentResponse);
|
---|
| 869 | else if(this.activity==BROWSING)
|
---|
| 870 | browseResponseObject.setContentForDocs(contentResponse);
|
---|
| 871 | }
|
---|
| 872 | }
|
---|
| 873 |
|
---|
| 874 | /** Performs a structureRetrieve and title metadata retrieve message-
|
---|
| 875 | * request for the docNode, but only iff the structure and title for
|
---|
| 876 | * that docNode is not already set.
|
---|
| 877 | * @param docNode is the DocumentNodeData object for which the title
|
---|
| 878 | * is to be retrieved along with the titles of all its descendants. */
|
---|
| 879 | public void retrieveTitledStructureFor(DocumentNodeData docNode) {
|
---|
| 880 | DocumentNodeData root = docNode.getRoot();
|
---|
| 881 | if(root == null) { //then its structure has not yet been set
|
---|
| 882 | // do a structure retrieve for this document:
|
---|
[22299] | 883 | String structureResponseXML =
|
---|
| 884 | dlAPIA.retrieveDocumentStructure(this.colName, new String[] { docNode.nodeID },
|
---|
| 885 | new String[] {"descendants"}, new String[]{""});
|
---|
[15222] | 886 | Element structureResponse = getResponseAsDOM(
|
---|
| 887 | "STRUCTURE: ", structureResponseXML);
|
---|
[22299] | 888 |
|
---|
[15222] | 889 | // Get the nodeStructure of this docNode, find its root and
|
---|
| 890 | // from there set all the descendents
|
---|
| 891 | // Instead of the following 2 statements can also do:
|
---|
| 892 | // queryResponseObj.setStructureForDocs(structureResponse);
|
---|
| 893 |
|
---|
| 894 | Element nodeStructure = ParseUtil.getFirstDescElementCalled(
|
---|
| 895 | structureResponse, GSXML.NODE_STRUCTURE_ELEM);
|
---|
| 896 |
|
---|
| 897 | // now we set the root and its descendents using whatever
|
---|
| 898 | ResponseData responseObject = browseResponseObject;
|
---|
| 899 | // true if(this.activity == BROWSING)
|
---|
| 900 | if(this.activity == SEARCHING)
|
---|
| 901 | responseObject = queryResponseObj;
|
---|
| 902 |
|
---|
| 903 | root = docNode.setDescendentsOfRootNode(nodeStructure,
|
---|
| 904 | responseObject.getIDToNodeMapping());
|
---|
| 905 |
|
---|
| 906 | // Now get only the DocumentNodeData elements in the root's
|
---|
| 907 | // descendents whose titles have not yet been set
|
---|
| 908 | String[] setTitleForTheseNodeIDs = root.getDescNodeIDsAsList(true);
|
---|
| 909 | // Will be null if all titles already set! But this should not be
|
---|
| 910 | // the case if we have just set the descendents of the root node
|
---|
| 911 | if(setTitleForTheseNodeIDs != null) {
|
---|
| 912 | // Retrieve the title metadata for these and set their titles
|
---|
| 913 | // with the response:
|
---|
| 914 | String titleMetaResponseXML = dlAPIA.retrieveTitleMetadata(
|
---|
| 915 | this.colName, setTitleForTheseNodeIDs);
|
---|
| 916 | Element titleMetaResponse = getResponseAsDOM(
|
---|
| 917 | "titleMetaResponseXML:", titleMetaResponseXML);
|
---|
| 918 |
|
---|
| 919 | // Use whatever responseObject is active to set the metadata
|
---|
| 920 | responseObject.setMetadataForDocuments(titleMetaResponse);
|
---|
| 921 | }
|
---|
| 922 | }
|
---|
| 923 | }
|
---|
| 924 |
|
---|
| 925 | /* BROWSE RELATED METHODS */
|
---|
| 926 | /** Given a ClassifierData object indicating what browsing category
|
---|
| 927 | * was chosen, this method will retrieve all its descendants in the
|
---|
| 928 | * hierarchy. Only the top-level descendents (children) of the
|
---|
| 929 | * classification will be set initially.
|
---|
| 930 | * @param classifier is the ClassifierData object whose children are
|
---|
| 931 | * to be retrieved. */
|
---|
| 932 | public void doBrowse(ClassifierData classifier) {
|
---|
[21835] | 933 | String[] classifierNames = { classifier.name };
|
---|
[15222] | 934 | String response = dlAPIA.retrieveBrowseStructure(
|
---|
[22299] | 935 | this.colName, this.serviceName, classifierNames,
|
---|
| 936 | new String[]{"entire"}, new String[]{""}); // structure and info
|
---|
[15222] | 937 |
|
---|
| 938 | browseResponseObject.clear();
|
---|
| 939 | Element responseMsgTag = this.getResponseAsDOM(
|
---|
| 940 | "browseResponse:", response);
|
---|
| 941 | browseResponseObject.setResponseData(responseMsgTag); //classifier.name
|
---|
| 942 |
|
---|
| 943 | LOG.debug(browseResponseObject.show());
|
---|
| 944 |
|
---|
| 945 | this.browsePanel.displayBrowseResults(browseResponseObject,
|
---|
| 946 | classifier.displayName);
|
---|
| 947 | this.browsePanel.validate();
|
---|
| 948 | }
|
---|
| 949 |
|
---|
| 950 | /** Given a ClassifierNodeData object for browsing, this method will
|
---|
| 951 | * set the classNode's children (previously retrieved) and retrieve
|
---|
| 952 | * all the children's metadata including the title.
|
---|
| 953 | * @param classNode is the ClassifierNodeData object whose title is to
|
---|
| 954 | * be retrieved along with the titles for its children. */
|
---|
| 955 | public void retrieveTitledStructureFor(ClassifierNodeData classNode) {
|
---|
| 956 | // we will only be setting the children in this method and retrieving
|
---|
| 957 | // the names for them, as it concerns a classifierNodeData (and not
|
---|
| 958 | // a documentNodeData).
|
---|
| 959 |
|
---|
| 960 | classNode.setChildren(browseResponseObject.getIDToNodeMapping());
|
---|
| 961 |
|
---|
| 962 | //String rootID = browseResponseObject.getRootClassifier().nodeID;
|
---|
| 963 |
|
---|
| 964 | NodeData[] children = classNode.getChildren();
|
---|
| 965 | Vector docNodeChildren = new Vector(children.length);
|
---|
| 966 | Vector classNodeChildren = new Vector(children.length);
|
---|
| 967 | //String nodeIDs[] = new String[children.length];
|
---|
| 968 | for(int i = 0; i < children.length; i++) {
|
---|
| 969 | // don't bother setting the metadata if it was
|
---|
| 970 | // already set (check for empty metadata
|
---|
| 971 | if(children[i].getMetadataList() == null) {
|
---|
| 972 | if(children[i] instanceof ClassifierNodeData)
|
---|
| 973 | classNodeChildren.add(children[i]);
|
---|
| 974 | else if(children[i] instanceof DocumentNodeData)
|
---|
| 975 | docNodeChildren.add(children[i]);
|
---|
| 976 | }
|
---|
| 977 | }
|
---|
| 978 | String[] nodeIDs = null;
|
---|
| 979 |
|
---|
| 980 | // First set the metadata for any classifiers:
|
---|
| 981 | if(classNodeChildren.size() > 0) {
|
---|
| 982 | nodeIDs = new String[classNodeChildren.size()];
|
---|
| 983 | for(int i = 0; i < nodeIDs.length; i++)
|
---|
| 984 | nodeIDs[i] = ((NodeData)classNodeChildren.get(i)).nodeID;
|
---|
| 985 |
|
---|
| 986 | // let's just retrieve all the metadata - need to display it
|
---|
| 987 | // soon anyway
|
---|
[22299] | 988 | String response = dlAPIA.retrieveBrowseMetadata(this.colName, this.serviceName,
|
---|
| 989 | nodeIDs, new String[]{"all"});
|
---|
[15222] | 990 | Element responseXML = this.getResponseAsDOM(
|
---|
| 991 | "MetadataRetrieve response: ", response);
|
---|
| 992 | browseResponseObject.setMetadataForClassifiers(responseXML);
|
---|
| 993 |
|
---|
| 994 | for(int i = 0; i < nodeIDs.length; i++)
|
---|
| 995 | LOG.debug("Title: "
|
---|
| 996 | + ((NodeData)classNodeChildren.get(i)).getTitle());
|
---|
| 997 | }
|
---|
| 998 |
|
---|
| 999 | nodeIDs = null;
|
---|
| 1000 | // Now set the metadata for any documentNodes for which metadata
|
---|
| 1001 | // has not been set yet
|
---|
| 1002 | if(docNodeChildren.size() > 0) {
|
---|
| 1003 | nodeIDs = new String[docNodeChildren.size()];
|
---|
| 1004 | for(int i = 0; i < nodeIDs.length; i++)
|
---|
| 1005 | nodeIDs[i] = ((NodeData)docNodeChildren.get(i)).nodeID;
|
---|
| 1006 |
|
---|
| 1007 | // let's just retrieve all the metadata - need to display it
|
---|
| 1008 | // soon anyway
|
---|
[22299] | 1009 | String response = dlAPIA.retrieveDocumentMetadata(this.colName, nodeIDs,
|
---|
| 1010 | new String[] {"all"});
|
---|
[15222] | 1011 | Element responseXML = this.getResponseAsDOM(
|
---|
| 1012 | "MetadataRetrieve response: ", response);
|
---|
| 1013 | browseResponseObject.setMetadataForDocuments(responseXML);
|
---|
| 1014 |
|
---|
| 1015 | for(int i = 0; i < nodeIDs.length; i++)
|
---|
| 1016 | LOG.debug("Title: "
|
---|
| 1017 | + ((NodeData)docNodeChildren.get(i)).getTitle());
|
---|
| 1018 | }
|
---|
| 1019 | }
|
---|
| 1020 |
|
---|
| 1021 | /** @return the baseURL of the active digital library interface object */
|
---|
| 1022 | public String getBaseURL() {
|
---|
| 1023 | return this.dlAPIA.getAssocFileBaseURL();
|
---|
| 1024 | }
|
---|
| 1025 |
|
---|
| 1026 | /** @return the filepath of the documentNode in the active digital library */
|
---|
| 1027 | public String getFilePath(DocumentNodeData docNode) {
|
---|
| 1028 | return this.dlAPIA.getAssocFileBaseURL(docNode);
|
---|
| 1029 | }
|
---|
| 1030 |
|
---|
| 1031 | /**
|
---|
| 1032 | * Changes the background colours of the client's user interface
|
---|
| 1033 | * based on what the active digital library is.
|
---|
| 1034 | * See files greenstone3/gli/classes/xml/config.xml and
|
---|
| 1035 | * greenstone3/gli/src/org/greenstone/gatherer/Configuration.java
|
---|
| 1036 | * @param DL indicates whether the active digital library is Greenstone or
|
---|
| 1037 | * Fedora (or neither, in which case the GUI defaults to the usual grey).
|
---|
| 1038 | * @see <a href="http://www.java2s.com/Code/Java/Swing-JFC/UIManagerresourcestotweakthelookofapplications.htm">Java UIManager tutorial</a>
|
---|
| 1039 | */
|
---|
| 1040 | public void changeUIColour(int DL)
|
---|
| 1041 | {
|
---|
| 1042 | ColourCombo.setColour(DL);
|
---|
| 1043 | ColourCombo.changeColor(this.collBox);
|
---|
| 1044 | ColourCombo.changeColor(this.collectionNameField);
|
---|
| 1045 | ColourCombo.changeColor(this.serviceBox);
|
---|
| 1046 |
|
---|
| 1047 | // change anonymous super panels' colours:
|
---|
| 1048 | ColourCombo.changeAncestorColor(this.collBox);
|
---|
| 1049 | ColourCombo.changeAncestorColor(this.serviceBox);
|
---|
| 1050 |
|
---|
| 1051 | // change tab pane panels and their colouring
|
---|
| 1052 | this.queryPanel.changeUIColour();
|
---|
| 1053 | this.browsePanel.changeUIColour();
|
---|
| 1054 | this.searchResultsDisplay.changeUIColour();
|
---|
| 1055 | }
|
---|
[26180] | 1056 |
|
---|
| 1057 |
|
---|
| 1058 | public int getActiveDL() {
|
---|
| 1059 | return dlChooser.getSelectedIndex(); // SELECT, GREENSTONE, or FEDORA
|
---|
| 1060 | }
|
---|
[15222] | 1061 |
|
---|
| 1062 | /** The main method of the GS3 java-client application. It instantiates
|
---|
| 1063 | * an instance of the GS3JavaClient main window and makes it visible. */
|
---|
| 1064 | public static void main(String[] args) {
|
---|
[15237] | 1065 | // set it up for logging
|
---|
| 1066 | final String logPropsFile = "log4j.properties";
|
---|
| 1067 | PropertyConfigurator.configure(logPropsFile);
|
---|
| 1068 |
|
---|
[15222] | 1069 | GS3JavaClient client = new GS3JavaClient();
|
---|
| 1070 | client.pack();
|
---|
[15483] | 1071 | // make the main window fullscreen (except for on Windows,
|
---|
| 1072 | // where it disappears under the bar at the bottom)
|
---|
| 1073 | java.awt.Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
|
---|
[15731] | 1074 | if(System.getProperty("os.name").toLowerCase().contains("windows")) {
|
---|
[15483] | 1075 | d.setSize(d.getWidth()-100, d.getHeight()-100);
|
---|
| 1076 | }
|
---|
| 1077 | client.setSize(d);
|
---|
[15222] | 1078 | client.setVisible(true);
|
---|
| 1079 | client.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
---|
| 1080 | }
|
---|
[15731] | 1081 | }
|
---|