[2143] | 1 | /*
|
---|
| 2 | * SimpleGraphicalClient.java
|
---|
| 3 | * Copyright (C) 2001 New Zealand Digital Library Project
|
---|
| 4 | *
|
---|
| 5 | * This program is free software; you can redistribute it and/or modify
|
---|
| 6 | * it under the terms of the GNU General Public License as published by
|
---|
| 7 | * the Free Software Foundation; either version 2 of the License, or
|
---|
| 8 | * (at your option) any later version.
|
---|
| 9 | *
|
---|
| 10 | * This program is distributed in the hope that it will be useful,
|
---|
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 13 | * GNU General Public License for more details.
|
---|
| 14 | *
|
---|
| 15 | * You should have received a copy of the GNU General Public License
|
---|
| 16 | * along with this program; if not, write to the Free Software
|
---|
| 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
| 18 | */
|
---|
[2142] | 19 | package org.nzdl.gsdl.SimpleGraphicalClient;
|
---|
| 20 |
|
---|
| 21 | import java.awt.*;
|
---|
| 22 | import java.awt.event.*;
|
---|
[2165] | 23 | import java.io.*;
|
---|
[2159] | 24 | import java.io.IOException;
|
---|
[2142] | 25 | import java.util.*;
|
---|
[2148] | 26 | import javax.swing.*;
|
---|
[2153] | 27 | import javax.swing.event.*;
|
---|
| 28 | import javax.swing.text.*;
|
---|
| 29 | import javax.swing.text.html.*;
|
---|
[2142] | 30 |
|
---|
[2153] | 31 |
|
---|
[2142] | 32 | // local libraries
|
---|
| 33 | import org.nzdl.gsdl.service.NzdlCollectionInfo;
|
---|
| 34 | import org.nzdl.gsdl.service.NzdlQuery;
|
---|
| 35 | import org.nzdl.gsdl.service.NzdlRequest;
|
---|
| 36 | import org.nzdl.gsdl.service.NzdlResponse;
|
---|
| 37 | import org.nzdl.gsdl.service.NzdlResultSet;
|
---|
| 38 | import org.nzdl.gsdl.service.NzdlService;
|
---|
| 39 | import org.nzdl.gsdl.service.NzdlServiceClient;
|
---|
[2190] | 40 | import org.nzdl.gsdl.util.NzdlPreferences;
|
---|
[2142] | 41 |
|
---|
| 42 |
|
---|
[2143] | 43 | /**
|
---|
[2153] | 44 | * A Class representing the Panel in which the Querying action happens.
|
---|
[2143] | 45 | *
|
---|
| 46 | * Does most of the actual `work' in the package.
|
---|
| 47 | *
|
---|
| 48 | * @author Dave Nichols ([email protected])
|
---|
| 49 | * @author stuart yeates ([email protected])
|
---|
| 50 | * @version $Revision: 2195 $
|
---|
[2159] | 51 | * @see org.nzdl.gsdl.service.SimpleGraphicalClient.SimpleGraphicalClient
|
---|
| 52 | * @see org.nzdl.gsdl.service.SimpleGraphicalClient.CSModel
|
---|
[2143] | 53 | * @see javax.swing.JPanel
|
---|
| 54 | */
|
---|
[2142] | 55 |
|
---|
| 56 | public class SearchPanel extends JPanel implements ActionListener, Constants
|
---|
| 57 | {
|
---|
| 58 |
|
---|
[2143] | 59 | CSModel csModel;
|
---|
[2154] | 60 | NzdlService nzdl;
|
---|
| 61 |
|
---|
[2143] | 62 | JLabel collectionLabel;
|
---|
[2195] | 63 | JButton collectionInfoButton;
|
---|
[2143] | 64 | JTextField searchTextField;
|
---|
| 65 | JButton searchButton;
|
---|
[2154] | 66 | JComboBox collectionList;
|
---|
[2143] | 67 | JPanel queryFormulationPanel, resultsPanel, dataPanel;
|
---|
| 68 | JPanel collectionListPanel, searchTextFieldPanel, searchButtonPanel;
|
---|
| 69 | JList resultsList;
|
---|
| 70 | JScrollPane scrollResultsPane;
|
---|
[2153] | 71 | JScrollPane scrollDataPane;
|
---|
| 72 | JFrame windowParent;
|
---|
[2165] | 73 | //JEditorPane documentPane;
|
---|
[2190] | 74 | JTextPane documentPane; // make this a JTextComponent ??
|
---|
| 75 | JTextArea documentArea;
|
---|
| 76 | JTextComponent documentComponent;
|
---|
| 77 | HTMLEditorKit htmlEditorKit = new HTMLEditorKit();
|
---|
| 78 | StyledEditorKit styledEditorKit = new StyledEditorKit();
|
---|
[2165] | 79 | GMLDocument htmlDoc = new GMLDocument();
|
---|
[2190] | 80 | DefaultStyledDocument defaultStyledDoc = new DefaultStyledDocument();
|
---|
[2165] | 81 | final static GMLDocument blankDoc = new GMLDocument();
|
---|
[2153] | 82 |
|
---|
[2167] | 83 | /**
|
---|
[2143] | 84 | * Construct and initialise a new SearchPanel
|
---|
| 85 | */
|
---|
| 86 |
|
---|
[2142] | 87 | public SearchPanel( CSModel newCsModel, JFrame parent)
|
---|
| 88 | {
|
---|
| 89 | super();
|
---|
[2153] | 90 | windowParent = parent;
|
---|
[2143] | 91 | csModel = newCsModel;
|
---|
[2154] | 92 | nzdl = csModel.getNzdlService();
|
---|
[2142] | 93 | setLayout( new BoxLayout(this, BoxLayout.Y_AXIS));
|
---|
[2143] | 94 | setBorder(BorderFactory.createTitledBorder("Search"));
|
---|
[2142] | 95 |
|
---|
| 96 |
|
---|
[2143] | 97 | searchTextField = new JTextField("Enter search terms here", 35) {
|
---|
| 98 | public boolean isRequestFocusEnabled(){
|
---|
| 99 | return true;
|
---|
| 100 | }
|
---|
| 101 | };
|
---|
| 102 | searchTextField.setText("Enter search terms here");
|
---|
| 103 | searchTextField.setFont(searchTextFieldFont);
|
---|
| 104 | searchTextField.setColumns(35);
|
---|
[2177] | 105 | searchTextField.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
[2143] | 106 | searchButton = new JButton("Search");
|
---|
[2142] | 107 |
|
---|
[2143] | 108 | searchButton.addActionListener(this);
|
---|
| 109 | //searchButton.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
|
---|
| 110 | searchButton.setPreferredSize(new Dimension(80, 20));
|
---|
[2142] | 111 |
|
---|
[2143] | 112 | collectionListPanel = new JPanel();
|
---|
[2177] | 113 | collectionListPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
[2143] | 114 | collectionListPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
|
---|
| 115 | collectionLabel = new JLabel("Collection: ");
|
---|
[2153] | 116 |
|
---|
[2143] | 117 | collectionList = new JComboBox(csModel.getCollectionList()){
|
---|
| 118 | public boolean isFocusTraversable() {
|
---|
| 119 | return false;
|
---|
| 120 | }
|
---|
| 121 | };
|
---|
[2195] | 122 | collectionInfoButton = new JButton("Info...");
|
---|
| 123 | collectionInfoButton.addActionListener(this);
|
---|
| 124 |
|
---|
[2143] | 125 | collectionListPanel.add(collectionLabel);
|
---|
| 126 | collectionListPanel.add(collectionList);
|
---|
[2195] | 127 | collectionListPanel.add(collectionInfoButton);
|
---|
[2142] | 128 |
|
---|
[2143] | 129 | searchTextFieldPanel = new JPanel();
|
---|
| 130 | searchTextFieldPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
|
---|
| 131 | searchTextFieldPanel.add(searchTextField);
|
---|
[2142] | 132 |
|
---|
[2143] | 133 | searchButtonPanel = new JPanel();
|
---|
| 134 | searchButtonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
---|
| 135 | searchButtonPanel.add(searchButton);
|
---|
[2142] | 136 |
|
---|
[2143] | 137 | queryFormulationPanel = new JPanel();
|
---|
| 138 | queryFormulationPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
| 139 | queryFormulationPanel.setLayout(new BoxLayout(queryFormulationPanel, BoxLayout.Y_AXIS));
|
---|
| 140 | queryFormulationPanel.add(Box.createHorizontalStrut(100));
|
---|
| 141 | queryFormulationPanel.add(collectionListPanel);
|
---|
| 142 | queryFormulationPanel.add(searchTextFieldPanel);
|
---|
| 143 | queryFormulationPanel.add(searchButtonPanel);
|
---|
[2142] | 144 |
|
---|
[2143] | 145 | resultsPanel = new JPanel();
|
---|
| 146 | resultsPanel.setLayout(new BorderLayout());
|
---|
| 147 | resultsPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
| 148 | ResultModel resultListModel = csModel.getResultsModel();
|
---|
| 149 | resultsList = new JList(resultListModel);
|
---|
| 150 | resultsList.setFont(resultsFont);
|
---|
[2177] | 151 | resultsList.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
[2143] | 152 | resultsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
---|
| 153 | scrollResultsPane = new JScrollPane(resultsList);
|
---|
| 154 | resultsPanel.add(scrollResultsPane, BorderLayout.CENTER);
|
---|
[2165] | 155 | csModel.addResult(Result.INITIAL_FAKE_RESULT);
|
---|
[2142] | 156 |
|
---|
[2143] | 157 | dataPanel = new JPanel();
|
---|
| 158 | dataPanel.setLayout(new BorderLayout());
|
---|
| 159 | dataPanel.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
|
---|
[2190] | 160 | documentPane = new JTextPane() { // to control scrolling for raw text docs
|
---|
| 161 | public boolean getScrollableTracksViewportWidth() {
|
---|
| 162 | if (getSize().width < getParent().getSize().width)
|
---|
| 163 | return true;
|
---|
| 164 | else return false;
|
---|
| 165 | }
|
---|
| 166 | public void setSize(Dimension d) {
|
---|
| 167 | if (d.width < getParent().getSize().width)
|
---|
| 168 | d.width = getParent().getSize().width;
|
---|
| 169 | super.setSize(d);
|
---|
| 170 | }
|
---|
| 171 | }; // end custom JTextPane
|
---|
[2153] | 172 | documentPane.setEditable(false);
|
---|
| 173 | documentPane.setFont(docFont);
|
---|
| 174 | documentPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
| 175 | //documentPane.setPreferredSize(new Dimension(100, 100));
|
---|
| 176 |
|
---|
| 177 | scrollDataPane = new JScrollPane(documentPane);
|
---|
[2150] | 178 | scrollDataPane.setPreferredSize(new Dimension(300, 300));
|
---|
[2143] | 179 | dataPanel.add(scrollDataPane, BorderLayout.CENTER);
|
---|
[2142] | 180 |
|
---|
[2143] | 181 | parent.getRootPane().setDefaultButton(searchButton);
|
---|
[2154] | 182 |
|
---|
[2143] | 183 | resultsList.addListSelectionListener(new ResultListSelectionHandler() );
|
---|
[2154] | 184 |
|
---|
[2143] | 185 | add(Box.createHorizontalStrut(400));
|
---|
| 186 | add(queryFormulationPanel);
|
---|
| 187 | add(resultsPanel);
|
---|
| 188 | add(dataPanel);
|
---|
| 189 | searchTextField.requestFocus();
|
---|
[2142] | 190 | }
|
---|
[2153] | 191 |
|
---|
[2148] | 192 | /** respond to the user pressing the Search button */
|
---|
[2153] | 193 |
|
---|
[2149] | 194 | public void actionPerformed(ActionEvent e) {
|
---|
| 195 | if (e.getSource() == searchButton ) { //assume only searchButton generates events
|
---|
[2165] | 196 | // cursor not set when RETURN pressed, only when button clicked ?
|
---|
[2154] | 197 | windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
---|
[2165] | 198 | //System.err.println("set wait cursor..");
|
---|
[2154] | 199 | String queryString = searchTextField.getText();
|
---|
| 200 | String collectionName = collectionList.getSelectedItem().toString();
|
---|
| 201 | System.err.println("Search started (" + collectionName + "): \"" + queryString + "\" ..." );
|
---|
[2149] | 202 | //send query to collection
|
---|
[2154] | 203 | NzdlQuery nzdlQuery = new NzdlQuery(queryString);
|
---|
[2149] | 204 | // return the first numResults that match
|
---|
| 205 | //query.setEndResults( 15 );
|
---|
[2154] | 206 | // "-1" means consider all the documents that match
|
---|
[2149] | 207 | nzdlQuery.setMaxDocs( -1 );
|
---|
| 208 | NzdlRequest request = new NzdlRequest( nzdlQuery );
|
---|
[2154] | 209 | NzdlResponse response = new NzdlResponse();
|
---|
[2165] | 210 |
|
---|
[2154] | 211 | nzdl.service( collectionName, request, response );
|
---|
[2165] | 212 | Date t8 = new Date();
|
---|
[2149] | 213 | NzdlResultSet results = response.getResultSet();
|
---|
[2165] | 214 | ArrayList docIDs = new ArrayList(results.getDocumentIDs());
|
---|
| 215 | // System.err.println("Size of docIDs = " + docIDs.size());
|
---|
[2149] | 216 | // paired collection of docIDs and Titles - but as Sets!
|
---|
| 217 | Map titleMetaData = csModel.getNzdlService().getMetaData( collectionName, docIDs, "Title" );
|
---|
| 218 | // created a paired collection of docIDs and Titles - as simple Strings!
|
---|
| 219 | HashMap titleMap = new HashMap();
|
---|
| 220 | for (ListIterator i = docIDs.listIterator(); i.hasNext(); ) {
|
---|
| 221 | String docID = (String) i.next();
|
---|
[2168] | 222 | //Set titleSet = (Set) titleMetaData.get( docID );
|
---|
| 223 | ArrayList titleList = new ArrayList((Set)titleMetaData.get(docID));
|
---|
[2149] | 224 | // use the first title as *the* title
|
---|
| 225 | titleMap.put(docID, titleList.get(0));
|
---|
| 226 | } // end for
|
---|
[2165] | 227 | Date t9 = new Date();
|
---|
| 228 | long sdiff = t9.getTime() - t8.getTime();
|
---|
| 229 | System.err.println("processing results = " + sdiff + " ms");
|
---|
[2154] | 230 | // update the results list
|
---|
| 231 | csModel.clearResults();
|
---|
[2165] | 232 |
|
---|
[2154] | 233 | if (docIDs.size() == 0 ) { // give some feedback for 0 results
|
---|
[2165] | 234 | csModel.addResult(Result.FAKE_RESULT);
|
---|
| 235 | //documentPane.setText("");
|
---|
| 236 | documentPane.setStyledDocument(blankDoc);
|
---|
[2149] | 237 | }
|
---|
| 238 | else { // there are some results
|
---|
| 239 | Iterator docIDsIterator = docIDs.iterator();
|
---|
[2154] | 240 | while (docIDsIterator.hasNext()) {
|
---|
[2149] | 241 | String resultDocID = (String) docIDsIterator.next();
|
---|
| 242 | csModel.addResult(new Result((String)titleMap.get(resultDocID), resultDocID, collectionName ));
|
---|
| 243 | } //end while
|
---|
[2190] | 244 | if (NzdlPreferences.getInstance().getBoolean(Constants.DISPLAY_FIRST_DOC))
|
---|
[2184] | 245 | resultsList.setSelectedIndex(0); // should be under Preference control!
|
---|
[2149] | 246 | } // end else
|
---|
[2162] | 247 | titleMap.clear();
|
---|
| 248 | titleMetaData.clear();
|
---|
| 249 | docIDs.clear();
|
---|
[2154] | 250 | windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
---|
[2149] | 251 | } // end if
|
---|
| 252 | else {
|
---|
[2195] | 253 | if (e.getSource() == collectionInfoButton) {
|
---|
| 254 | //System.err.println("colllection info button pressed");
|
---|
| 255 | CollectionInfoDialog cid = new CollectionInfoDialog(windowParent, collectionList.getSelectedItem().toString(), csModel);
|
---|
| 256 | }
|
---|
| 257 | else {
|
---|
| 258 | System.err.println("unknown Action event in SearchPanel");
|
---|
| 259 | }
|
---|
| 260 | }
|
---|
[2154] | 261 | } //end actionPerformed
|
---|
| 262 |
|
---|
[2149] | 263 | /** handles selection events in the results list so that when the
|
---|
| 264 | user selects a new title (say) the document contents is
|
---|
| 265 | automatically displayed in the main panel */
|
---|
[2154] | 266 |
|
---|
[2149] | 267 | class ResultListSelectionHandler implements ListSelectionListener {
|
---|
[2165] | 268 |
|
---|
| 269 | // private Result previousSelection = null;
|
---|
| 270 |
|
---|
[2149] | 271 | public void valueChanged(ListSelectionEvent e) {
|
---|
| 272 | // get the result object from the SelectedIndex
|
---|
| 273 | // assume we only get here with events from resultsList
|
---|
[2165] | 274 | if (e.getValueIsAdjusting()) { return; }
|
---|
[2149] | 275 | Result result = (Result) resultsList.getSelectedValue();
|
---|
[2165] | 276 | // System.err.println("result = " + result);
|
---|
| 277 | // System.err.println("fake result = " + Result.FAKE_RESULT);
|
---|
| 278 | if ((result == Result.FAKE_RESULT) || (result == Result.INITIAL_FAKE_RESULT)) {
|
---|
| 279 | //documentPane.setText("");
|
---|
| 280 | documentPane.setStyledDocument( blankDoc );
|
---|
| 281 | System.err.println("clicked on fake result");
|
---|
[2149] | 282 | }
|
---|
[2190] | 283 | else {
|
---|
| 284 | // a real result representing a real document to deal with
|
---|
[2165] | 285 |
|
---|
[2153] | 286 | windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
---|
[2190] | 287 | //trash the old htmlDoc for memory/garbage collection
|
---|
[2162] | 288 | try {
|
---|
| 289 | if (htmlDoc != null)
|
---|
| 290 | htmlDoc.remove(0, htmlDoc.getLength());
|
---|
[2190] | 291 | if (defaultStyledDoc != null)
|
---|
| 292 | defaultStyledDoc.remove(0, defaultStyledDoc.getLength());
|
---|
[2162] | 293 | } catch (Exception exception) {
|
---|
| 294 | throw new Error (exception.toString());
|
---|
| 295 | }
|
---|
[2190] | 296 | defaultStyledDoc = new DefaultStyledDocument();
|
---|
[2165] | 297 | htmlDoc = new GMLDocument();
|
---|
[2190] | 298 |
|
---|
| 299 | try { // get the document
|
---|
[2168] | 300 | String docContents = csModel.getNzdlService().getDocument(result.getCollectionName(), result.getDocID());
|
---|
[2190] | 301 | StringReader sr = new StringReader( docContents);
|
---|
| 302 | if (NzdlPreferences.getInstance().getBoolean(Constants.RAW_TEXT)) { // display the document as raw text
|
---|
| 303 | documentPane.setEditorKit(styledEditorKit);
|
---|
| 304 | styledEditorKit.read( sr, defaultStyledDoc, 0);
|
---|
| 305 | documentPane.setDocument(defaultStyledDoc);
|
---|
| 306 | }
|
---|
| 307 | else { // treat as HTML
|
---|
| 308 | documentPane.setEditorKit(htmlEditorKit);
|
---|
| 309 | htmlEditorKit.read( sr, htmlDoc, 0);
|
---|
| 310 | documentPane.setStyledDocument( htmlDoc );
|
---|
| 311 | }
|
---|
| 312 | // htmlEditorKit.read( new StringReader(csModel.getNzdlService().getDocument(result.getCollectionName(), result.getDocID())), htmlDoc, 0);
|
---|
| 313 | }
|
---|
[2153] | 314 | catch(BadLocationException badLocException)
|
---|
| 315 | {
|
---|
[2165] | 316 | System.err.println("Bad Location Exception in creating HTML doc" + badLocException);
|
---|
[2153] | 317 | }
|
---|
| 318 | catch(IOException ioException)
|
---|
| 319 | {
|
---|
| 320 | System.err.println("IO Exception whilst reading doc contents" + ioException);
|
---|
[2168] | 321 | }
|
---|
[2165] | 322 |
|
---|
[2190] | 323 | //documentPane.setStyledDocument( htmlDoc );
|
---|
| 324 | // should check for empty document here
|
---|
[2167] | 325 | documentPane.setCaretPosition(1);
|
---|
[2190] | 326 | // we might not be using htmlDoc at this point!!
|
---|
[2195] | 327 | htmlDoc.getImageData(nzdl, result.getCollectionName());
|
---|
[2153] | 328 | windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
---|
[2184] | 329 | //System.err.println("prefix = " + nzdl.getCollectionInfo(result.getCollectionName()).getHTTPPrefix());
|
---|
[2147] | 330 | }
|
---|
[2149] | 331 | } //end valueChanged
|
---|
| 332 | }//end ResultListSelectionHandler
|
---|
[2154] | 333 |
|
---|
[2142] | 334 | } //end SearchPanel
|
---|