/* * SimpleGraphicalClient.java * Copyright (C) 2001 New Zealand Digital Library Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.nzdl.gsdl.SimpleGraphicalClient; import java.awt.*; import java.awt.event.*; import java.io.*; import java.io.IOException; import java.util.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.text.html.*; // local libraries import org.nzdl.gsdl.service.NzdlCollectionInfo; import org.nzdl.gsdl.service.NzdlQuery; import org.nzdl.gsdl.service.NzdlRequest; import org.nzdl.gsdl.service.NzdlResponse; import org.nzdl.gsdl.service.NzdlResultSet; import org.nzdl.gsdl.service.NzdlService; import org.nzdl.gsdl.service.NzdlServiceClient; import org.nzdl.gsdl.util.NzdlPreferences; /** * A Class representing the Panel in which the Querying action happens. * * Does most of the actual `work' in the package. * * @author Dave Nichols (daven@cs.waikato.ac.nz) * @author stuart yeates (say1@cs.waikato.ac.nz) * @version $Revision: 2195 $ * @see org.nzdl.gsdl.service.SimpleGraphicalClient.SimpleGraphicalClient * @see org.nzdl.gsdl.service.SimpleGraphicalClient.CSModel * @see javax.swing.JPanel */ public class SearchPanel extends JPanel implements ActionListener, Constants { CSModel csModel; NzdlService nzdl; JLabel collectionLabel; JButton collectionInfoButton; JTextField searchTextField; JButton searchButton; JComboBox collectionList; JPanel queryFormulationPanel, resultsPanel, dataPanel; JPanel collectionListPanel, searchTextFieldPanel, searchButtonPanel; JList resultsList; JScrollPane scrollResultsPane; JScrollPane scrollDataPane; JFrame windowParent; //JEditorPane documentPane; JTextPane documentPane; // make this a JTextComponent ?? JTextArea documentArea; JTextComponent documentComponent; HTMLEditorKit htmlEditorKit = new HTMLEditorKit(); StyledEditorKit styledEditorKit = new StyledEditorKit(); GMLDocument htmlDoc = new GMLDocument(); DefaultStyledDocument defaultStyledDoc = new DefaultStyledDocument(); final static GMLDocument blankDoc = new GMLDocument(); /** * Construct and initialise a new SearchPanel */ public SearchPanel( CSModel newCsModel, JFrame parent) { super(); windowParent = parent; csModel = newCsModel; nzdl = csModel.getNzdlService(); setLayout( new BoxLayout(this, BoxLayout.Y_AXIS)); setBorder(BorderFactory.createTitledBorder("Search")); searchTextField = new JTextField("Enter search terms here", 35) { public boolean isRequestFocusEnabled(){ return true; } }; searchTextField.setText("Enter search terms here"); searchTextField.setFont(searchTextFieldFont); searchTextField.setColumns(35); searchTextField.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); searchButton = new JButton("Search"); searchButton.addActionListener(this); //searchButton.setBorder(BorderFactory.createEmptyBorder(2,2,2,2)); searchButton.setPreferredSize(new Dimension(80, 20)); collectionListPanel = new JPanel(); collectionListPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); collectionListPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); collectionLabel = new JLabel("Collection: "); collectionList = new JComboBox(csModel.getCollectionList()){ public boolean isFocusTraversable() { return false; } }; collectionInfoButton = new JButton("Info..."); collectionInfoButton.addActionListener(this); collectionListPanel.add(collectionLabel); collectionListPanel.add(collectionList); collectionListPanel.add(collectionInfoButton); searchTextFieldPanel = new JPanel(); searchTextFieldPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); searchTextFieldPanel.add(searchTextField); searchButtonPanel = new JPanel(); searchButtonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); searchButtonPanel.add(searchButton); queryFormulationPanel = new JPanel(); queryFormulationPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); queryFormulationPanel.setLayout(new BoxLayout(queryFormulationPanel, BoxLayout.Y_AXIS)); queryFormulationPanel.add(Box.createHorizontalStrut(100)); queryFormulationPanel.add(collectionListPanel); queryFormulationPanel.add(searchTextFieldPanel); queryFormulationPanel.add(searchButtonPanel); resultsPanel = new JPanel(); resultsPanel.setLayout(new BorderLayout()); resultsPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); ResultModel resultListModel = csModel.getResultsModel(); resultsList = new JList(resultListModel); resultsList.setFont(resultsFont); resultsList.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); resultsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); scrollResultsPane = new JScrollPane(resultsList); resultsPanel.add(scrollResultsPane, BorderLayout.CENTER); csModel.addResult(Result.INITIAL_FAKE_RESULT); dataPanel = new JPanel(); dataPanel.setLayout(new BorderLayout()); dataPanel.setBorder(BorderFactory.createEmptyBorder(3,3,3,3)); documentPane = new JTextPane() { // to control scrolling for raw text docs public boolean getScrollableTracksViewportWidth() { if (getSize().width < getParent().getSize().width) return true; else return false; } public void setSize(Dimension d) { if (d.width < getParent().getSize().width) d.width = getParent().getSize().width; super.setSize(d); } }; // end custom JTextPane documentPane.setEditable(false); documentPane.setFont(docFont); documentPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); //documentPane.setPreferredSize(new Dimension(100, 100)); scrollDataPane = new JScrollPane(documentPane); scrollDataPane.setPreferredSize(new Dimension(300, 300)); dataPanel.add(scrollDataPane, BorderLayout.CENTER); parent.getRootPane().setDefaultButton(searchButton); resultsList.addListSelectionListener(new ResultListSelectionHandler() ); add(Box.createHorizontalStrut(400)); add(queryFormulationPanel); add(resultsPanel); add(dataPanel); searchTextField.requestFocus(); } /** respond to the user pressing the Search button */ public void actionPerformed(ActionEvent e) { if (e.getSource() == searchButton ) { //assume only searchButton generates events // cursor not set when RETURN pressed, only when button clicked ? windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); //System.err.println("set wait cursor.."); String queryString = searchTextField.getText(); String collectionName = collectionList.getSelectedItem().toString(); System.err.println("Search started (" + collectionName + "): \"" + queryString + "\" ..." ); //send query to collection NzdlQuery nzdlQuery = new NzdlQuery(queryString); // return the first numResults that match //query.setEndResults( 15 ); // "-1" means consider all the documents that match nzdlQuery.setMaxDocs( -1 ); NzdlRequest request = new NzdlRequest( nzdlQuery ); NzdlResponse response = new NzdlResponse(); nzdl.service( collectionName, request, response ); Date t8 = new Date(); NzdlResultSet results = response.getResultSet(); ArrayList docIDs = new ArrayList(results.getDocumentIDs()); // System.err.println("Size of docIDs = " + docIDs.size()); // paired collection of docIDs and Titles - but as Sets! Map titleMetaData = csModel.getNzdlService().getMetaData( collectionName, docIDs, "Title" ); // created a paired collection of docIDs and Titles - as simple Strings! HashMap titleMap = new HashMap(); for (ListIterator i = docIDs.listIterator(); i.hasNext(); ) { String docID = (String) i.next(); //Set titleSet = (Set) titleMetaData.get( docID ); ArrayList titleList = new ArrayList((Set)titleMetaData.get(docID)); // use the first title as *the* title titleMap.put(docID, titleList.get(0)); } // end for Date t9 = new Date(); long sdiff = t9.getTime() - t8.getTime(); System.err.println("processing results = " + sdiff + " ms"); // update the results list csModel.clearResults(); if (docIDs.size() == 0 ) { // give some feedback for 0 results csModel.addResult(Result.FAKE_RESULT); //documentPane.setText(""); documentPane.setStyledDocument(blankDoc); } else { // there are some results Iterator docIDsIterator = docIDs.iterator(); while (docIDsIterator.hasNext()) { String resultDocID = (String) docIDsIterator.next(); csModel.addResult(new Result((String)titleMap.get(resultDocID), resultDocID, collectionName )); } //end while if (NzdlPreferences.getInstance().getBoolean(Constants.DISPLAY_FIRST_DOC)) resultsList.setSelectedIndex(0); // should be under Preference control! } // end else titleMap.clear(); titleMetaData.clear(); docIDs.clear(); windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } // end if else { if (e.getSource() == collectionInfoButton) { //System.err.println("colllection info button pressed"); CollectionInfoDialog cid = new CollectionInfoDialog(windowParent, collectionList.getSelectedItem().toString(), csModel); } else { System.err.println("unknown Action event in SearchPanel"); } } } //end actionPerformed /** handles selection events in the results list so that when the user selects a new title (say) the document contents is automatically displayed in the main panel */ class ResultListSelectionHandler implements ListSelectionListener { // private Result previousSelection = null; public void valueChanged(ListSelectionEvent e) { // get the result object from the SelectedIndex // assume we only get here with events from resultsList if (e.getValueIsAdjusting()) { return; } Result result = (Result) resultsList.getSelectedValue(); // System.err.println("result = " + result); // System.err.println("fake result = " + Result.FAKE_RESULT); if ((result == Result.FAKE_RESULT) || (result == Result.INITIAL_FAKE_RESULT)) { //documentPane.setText(""); documentPane.setStyledDocument( blankDoc ); System.err.println("clicked on fake result"); } else { // a real result representing a real document to deal with windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); //trash the old htmlDoc for memory/garbage collection try { if (htmlDoc != null) htmlDoc.remove(0, htmlDoc.getLength()); if (defaultStyledDoc != null) defaultStyledDoc.remove(0, defaultStyledDoc.getLength()); } catch (Exception exception) { throw new Error (exception.toString()); } defaultStyledDoc = new DefaultStyledDocument(); htmlDoc = new GMLDocument(); try { // get the document String docContents = csModel.getNzdlService().getDocument(result.getCollectionName(), result.getDocID()); StringReader sr = new StringReader( docContents); if (NzdlPreferences.getInstance().getBoolean(Constants.RAW_TEXT)) { // display the document as raw text documentPane.setEditorKit(styledEditorKit); styledEditorKit.read( sr, defaultStyledDoc, 0); documentPane.setDocument(defaultStyledDoc); } else { // treat as HTML documentPane.setEditorKit(htmlEditorKit); htmlEditorKit.read( sr, htmlDoc, 0); documentPane.setStyledDocument( htmlDoc ); } // htmlEditorKit.read( new StringReader(csModel.getNzdlService().getDocument(result.getCollectionName(), result.getDocID())), htmlDoc, 0); } catch(BadLocationException badLocException) { System.err.println("Bad Location Exception in creating HTML doc" + badLocException); } catch(IOException ioException) { System.err.println("IO Exception whilst reading doc contents" + ioException); } //documentPane.setStyledDocument( htmlDoc ); // should check for empty document here documentPane.setCaretPosition(1); // we might not be using htmlDoc at this point!! htmlDoc.getImageData(nzdl, result.getCollectionName()); windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); //System.err.println("prefix = " + nzdl.getCollectionInfo(result.getCollectionName()).getHTTPPrefix()); } } //end valueChanged }//end ResultListSelectionHandler } //end SearchPanel