source: trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/SearchPanel.java@ 2264

Last change on this file since 2264 was 2256, checked in by daven, 23 years ago

added ranked and boolean searching options to the interface.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 15.7 KB
Line 
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 */
19package org.nzdl.gsdl.SimpleGraphicalClient;
20
21import java.awt.*;
22import java.awt.event.*;
23import java.io.*;
24import java.io.IOException;
25import java.util.*;
26import javax.swing.*;
27import javax.swing.event.*;
28import javax.swing.text.*;
29import javax.swing.text.html.*;
30
31
32// local libraries
33import org.nzdl.gsdl.service.NzdlCollectionInfo;
34import org.nzdl.gsdl.service.NzdlQuery;
35import org.nzdl.gsdl.service.NzdlRequest;
36import org.nzdl.gsdl.service.NzdlResponse;
37import org.nzdl.gsdl.service.NzdlResultSet;
38import org.nzdl.gsdl.service.NzdlService;
39import org.nzdl.gsdl.service.NzdlServiceClient;
40import org.nzdl.gsdl.util.*;
41
42
43/**
44 * A Class representing the Panel in which the Querying action happens.
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: 2256 $
51 * @see org.nzdl.gsdl.service.SimpleGraphicalClient.SimpleGraphicalClient
52 * @see org.nzdl.gsdl.service.SimpleGraphicalClient.CSModel
53 * @see javax.swing.JPanel
54 */
55
56public class SearchPanel extends JPanel implements ActionListener, Constants
57{
58
59 CSModel csModel;
60 NzdlService nzdl;
61
62 JLabel collectionLabel;
63 JButton collectionInfoButton;
64 JTextField searchTextField;
65 JButton searchButton;
66 JComboBox collectionList;
67 JPanel queryFormulationPanel, resultsPanel, dataPanel, optionsPanel;
68 JPanel queryTypePanel, searchControlPanel;
69 JPanel collectionListPanel, searchTextFieldPanel, searchButtonPanel;
70 JList resultsList;
71 JCheckBox stemCheckBox, caseFoldCheckBox;
72 JRadioButton rankedRadioButton, booleanRadioButton;
73 ButtonGroup buttonGroup;
74 JScrollPane scrollResultsPane;
75 JScrollPane scrollDataPane;
76 JFrame windowParent;
77 //JEditorPane documentPane;
78 JTextPane documentPane; // make this a JTextComponent ??
79 JTextArea documentArea;
80 JTextComponent documentComponent;
81 HTMLEditorKit htmlEditorKit = new HTMLEditorKit();
82 StyledEditorKit styledEditorKit = new StyledEditorKit();
83 GMLDocument htmlDoc = new GMLDocument();
84 DefaultStyledDocument defaultStyledDoc = new DefaultStyledDocument();
85 final static GMLDocument blankDoc = new GMLDocument();
86
87 /**
88 * Construct and initialise a new SearchPanel
89 */
90
91 public SearchPanel( CSModel newCsModel, JFrame parent)
92 {
93 super();
94 windowParent = parent;
95 csModel = newCsModel;
96 nzdl = csModel.getNzdlService();
97 setLayout( new BoxLayout(this, BoxLayout.Y_AXIS));
98 setBorder(BorderFactory.createTitledBorder("Search"));
99
100
101 searchTextField = new JTextField("Enter search terms here", 35) {
102 public boolean isRequestFocusEnabled(){
103 return true;
104 }
105 };
106 searchTextField.setText("Enter search terms here");
107 searchTextField.setFont(searchTextFieldFont);
108 searchTextField.setColumns(35);
109 searchTextField.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
110 searchButton = new JButton("Search");
111
112 searchButton.addActionListener(this);
113 //searchButton.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
114 searchButton.setPreferredSize(new Dimension(80, 20));
115
116 collectionListPanel = new JPanel();
117 collectionListPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
118 collectionListPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
119 collectionLabel = new JLabel("Collection: ");
120
121 collectionList = new JComboBox(csModel.getCollectionList()){
122 public boolean isFocusTraversable() {
123 return false;
124 }
125 };
126 collectionList.setEditable(false);
127
128 collectionInfoButton = new JButton("Info...") {
129 public String getToolTipText(MouseEvent e) {
130 return "Collection information for '" + csModel.getLongCollectionName((String)collectionList.getSelectedItem()) +"'";
131 }
132 };
133 ToolTipManager.sharedInstance().registerComponent(collectionInfoButton);
134 collectionInfoButton.addActionListener(this);
135
136 collectionListPanel.add(collectionLabel);
137 collectionListPanel.add(collectionList);
138 collectionListPanel.add(collectionInfoButton);
139
140 searchTextFieldPanel = new JPanel();
141 searchTextFieldPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
142 searchTextFieldPanel.add(searchTextField);
143
144 optionsPanel = new JPanel();
145
146 queryTypePanel = new JPanel();
147 queryTypePanel.setLayout(new GridLayout(2,1));
148 rankedRadioButton = new JRadioButton("ranked");
149 rankedRadioButton.setActionCommand(rankedRadioButton.getText());
150 rankedRadioButton.setSelected(rankedRadioButton.getText() == NzdlConstants.DEFAULT_QUERY_TYPE);
151 rankedRadioButton.setToolTipText("Display results in a ranked list");
152
153 booleanRadioButton = new JRadioButton("boolean");
154 booleanRadioButton.setActionCommand(booleanRadioButton.getText());
155 booleanRadioButton.setSelected(booleanRadioButton.getText() == NzdlConstants.DEFAULT_QUERY_TYPE);
156 booleanRadioButton.setToolTipText("Allows the use of Boolean operators: AND(&) OR(|) and NOT(!)");
157 buttonGroup = new ButtonGroup();
158 buttonGroup.add(rankedRadioButton);
159 buttonGroup.add(booleanRadioButton);
160 queryTypePanel.add(rankedRadioButton);
161 queryTypePanel.add(booleanRadioButton);
162
163 stemCheckBox = new JCheckBox("Stemming", true);
164 stemCheckBox.setToolTipText("Strip endings such as '...ing', '...ed'");
165 caseFoldCheckBox = new JCheckBox("Match case", false);
166 caseFoldCheckBox.setToolTipText("Only match when the case is the same");
167
168 optionsPanel.add(queryTypePanel);
169 optionsPanel.add(stemCheckBox);
170 optionsPanel.add(caseFoldCheckBox);
171
172 searchButtonPanel = new JPanel();
173 searchButtonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
174 searchButtonPanel.add(searchButton);
175
176 searchControlPanel = new JPanel();
177 searchControlPanel.setLayout(new BorderLayout());
178 searchControlPanel.add(optionsPanel, BorderLayout.WEST);
179 searchControlPanel.add(searchButtonPanel, BorderLayout.EAST);
180
181 queryFormulationPanel = new JPanel();
182 queryFormulationPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
183 queryFormulationPanel.setLayout(new BoxLayout(queryFormulationPanel, BoxLayout.Y_AXIS));
184 queryFormulationPanel.add(Box.createHorizontalStrut(100));
185 queryFormulationPanel.add(collectionListPanel);
186 queryFormulationPanel.add(searchTextFieldPanel);
187 queryFormulationPanel.add(searchControlPanel);
188
189 resultsPanel = new JPanel();
190 resultsPanel.setLayout(new BorderLayout());
191 resultsPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
192 ResultModel resultListModel = csModel.getResultsModel();
193 resultsList = new JList(resultListModel);
194 resultsList.setFont(resultsFont);
195 resultsList.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
196 resultsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
197 scrollResultsPane = new JScrollPane(resultsList);
198 resultsPanel.add(scrollResultsPane, BorderLayout.CENTER);
199 csModel.addResult(Result.INITIAL_FAKE_RESULT);
200
201 dataPanel = new JPanel();
202 dataPanel.setLayout(new BorderLayout());
203 dataPanel.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
204 documentPane = new JTextPane() { // to control scrolling for raw text docs
205 public boolean getScrollableTracksViewportWidth() {
206 if (getSize().width < getParent().getSize().width)
207 return true;
208 else return false;
209 }
210 public void setSize(Dimension d) {
211 if (d.width < getParent().getSize().width)
212 d.width = getParent().getSize().width;
213 super.setSize(d);
214 }
215 }; // end custom JTextPane
216
217 documentPane.setEditable(false);
218 documentPane.setFont(docFont);
219 documentPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
220 //documentPane.setPreferredSize(new Dimension(100, 100));
221
222 scrollDataPane = new JScrollPane(documentPane);
223 scrollDataPane.setPreferredSize(new Dimension(300, 300));
224 dataPanel.add(scrollDataPane, BorderLayout.CENTER);
225
226 parent.getRootPane().setDefaultButton(searchButton);
227
228 resultsList.addListSelectionListener(new ResultListSelectionHandler() );
229
230 add(Box.createHorizontalStrut(400));
231 add(queryFormulationPanel);
232 add(resultsPanel);
233 add(dataPanel);
234 searchTextField.requestFocus();
235 }
236
237 /** respond to the user pressing the Search button */
238
239 public void actionPerformed(ActionEvent e) {
240 String collectionName = collectionList.getSelectedItem().toString();
241 if (e.getSource() == searchButton ) {
242 // cursor not set when RETURN pressed, only when button clicked ?
243 windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
244 String queryString = searchTextField.getText();
245 System.err.println("Search started (" + collectionName + "): \"" + queryString + "\" ..." );
246 //send query to collection
247 NzdlQuery nzdlQuery = new NzdlQuery(queryString);
248 nzdlQuery.setQueryType(buttonGroup.getSelection().getActionCommand());
249 System.err.println(buttonGroup.getSelection().getActionCommand());
250 //nzdlQuery.setQueryType("boolean");
251 nzdlQuery.setStemming(stemCheckBox.isSelected());
252 // interface reverses underlying logic so negate UI element state
253 nzdlQuery.setCaseFolding(! caseFoldCheckBox.isSelected());
254
255 // return the first numResults that match
256 nzdlQuery.setEndResults( -1 );
257 // "-1" means consider all the documents that match
258 nzdlQuery.setMaxDocs( -1 );
259
260 NzdlRequest request = new NzdlRequest( nzdlQuery );
261 NzdlResponse response = new NzdlResponse();
262
263 nzdl.service( collectionName, request, response );
264 NzdlResultSet results = response.getResultSet();
265 ArrayList docIDs = new ArrayList(results.getDocumentIDs());
266 // System.err.println("Size of docIDs = " + docIDs.size());
267 // paired collection of docIDs and Titles - but as Sets!
268 Map titleMetaData = nzdl.getMetaData( collectionName, docIDs, "Title" );
269 // created a paired collection of docIDs and Titles - as simple Strings!
270 HashMap titleMap = new HashMap();
271 for (ListIterator i = docIDs.listIterator(); i.hasNext(); ) {
272 String docID = (String) i.next();
273 //Set titleSet = (Set) titleMetaData.get( docID );
274 ArrayList titleList = new ArrayList((Set)titleMetaData.get(docID));
275 // use the first title as *the* title
276 titleMap.put(docID, titleList.get(0));
277 } // end for
278 // update the results list
279 csModel.clearResults();
280
281 if (docIDs.size() == 0 ) { // give some feedback for 0 results
282 csModel.addResult(Result.FAKE_RESULT);
283 documentPane.setStyledDocument(blankDoc);
284 }
285 else { // there are some results
286 Iterator docIDsIterator = docIDs.iterator();
287 while (docIDsIterator.hasNext()) {
288 String resultDocID = (String) docIDsIterator.next();
289 csModel.addResult(new Result((String)titleMap.get(resultDocID), resultDocID, collectionName ));
290 } //end while
291 if (NzdlPreferences.getInstance().getBoolean(Constants.DISPLAY_FIRST_DOC))
292 resultsList.setSelectedIndex(0);
293 } // end else
294
295
296 csModel.getQueryHistoryModel().add( new QueryHistoryItem(new Query(queryString), new Date(), collectionName, "user",docIDs.size() ));
297
298 titleMap.clear();
299 titleMetaData.clear();
300 docIDs.clear();
301 windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
302 } // end if
303 else {
304 if (e.getSource() == collectionInfoButton) {
305 CollectionInfoDialog cid = new CollectionInfoDialog(windowParent, collectionName, csModel);
306 }
307 else {
308 System.err.println("unknown Action event in SearchPanel");
309 }
310 }
311 } //end actionPerformed
312
313 /** handles selection events in the results list so that when the
314 user selects a new title (say) the document contents is
315 automatically displayed in the main panel */
316
317 class ResultListSelectionHandler implements ListSelectionListener {
318
319 // private Result previousSelection = null;
320
321 public void valueChanged(ListSelectionEvent e) {
322 // get the result object from the SelectedIndex
323 // assume we only get here with events from resultsList
324 int docLength = 0;
325 if (e.getValueIsAdjusting()) { return; }
326 Result result = (Result) resultsList.getSelectedValue();
327 if ((result == Result.FAKE_RESULT) || (result == Result.INITIAL_FAKE_RESULT)) {
328 documentPane.setStyledDocument( blankDoc );
329 System.err.println("clicked on fake result");
330 }
331 else { // a real result representing a real document to deal with
332
333 windowParent.setCursor(WAIT_CURSOR);
334
335 deleteDocContents(); // for memory/garbage collection
336
337 StringReader sr = new StringReader(nzdl.getDocument(result.getCollectionName(), result.getDocID()));
338
339 if (NzdlPreferences.getInstance().getBoolean(Constants.RAW_TEXT))
340 // display the document as raw text
341 displayAsRawText(sr);
342 else {
343 // treat as HTML
344 displayAsHTML(sr);
345 //htmlDoc.getImageData(nzdl, result.getCollectionName());
346 }
347
348 windowParent.setCursor(NORMAL_CURSOR);
349 }
350 } //end valueChanged
351 }//end ResultListSelectionHandler
352
353
354
355 private void deleteDocContents() {
356 //trash the old htmlDoc for memory/garbage collection
357 try {
358 if (htmlDoc != null)
359 htmlDoc.remove(0, htmlDoc.getLength());
360 if (defaultStyledDoc != null)
361 defaultStyledDoc.remove(0, defaultStyledDoc.getLength());
362 }
363 catch (Exception exception) {
364 throw new Error (exception.toString());
365 }
366 } // end deleteDocContents
367
368
369 public void switchToRawText() {
370 windowParent.setCursor(WAIT_CURSOR);
371 System.err.println("switching to raw text");
372 displayAsRawText(new StringReader(documentPane.getText()));
373 windowParent.setCursor(NORMAL_CURSOR);
374 }
375
376 public void displayAsRawText(StringReader sr) {
377 defaultStyledDoc = new DefaultStyledDocument();
378 documentPane.setEditorKit(styledEditorKit);
379 try {
380 styledEditorKit.read( sr, defaultStyledDoc, 0);
381 }
382 catch (Exception e) {
383 System.err.println(e);
384 }
385 documentPane.setDocument(defaultStyledDoc);
386 setCaretToStart(defaultStyledDoc.getLength());
387 } // end displayAsRawText
388
389
390 public void switchToHTML() {
391 windowParent.setCursor(WAIT_CURSOR);
392 System.err.println("switching to HTML");
393 displayAsHTML(new StringReader(documentPane.getText()));
394 windowParent.setCursor(NORMAL_CURSOR);
395 }
396
397 public void displayAsHTML(StringReader sr) {
398 htmlDoc = new GMLDocument();
399 documentPane.setEditorKit(htmlEditorKit);
400 try {
401 htmlEditorKit.read( sr, htmlDoc, 0);
402 }
403 catch (Exception e) {
404 System.err.println(e);
405 }
406 documentPane.setStyledDocument( htmlDoc );
407 setCaretToStart(htmlDoc.getLength());
408 } // end displayAsHTML
409
410
411 private void setCaretToStart(int docLength) {
412 // it seems as if they haven't considered
413 // documents with > MAX_INT num of chars ...
414 if (docLength > 0)
415 documentPane.setCaretPosition(1);
416 }
417
418
419 } //end SearchPanel
Note: See TracBrowser for help on using the repository browser.