Changeset 1625 for trunk/gsdl
- Timestamp:
- 2000-10-27T17:16:16+13:00 (24 years ago)
- Location:
- trunk/gsdl/src/phind/client
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gsdl/src/phind/client/Phind.java
r1621 r1625 1 /* 2 3 Phind.java 4 5 Version 2.2.1 6 Gordon Paynter ([email protected]) 7 8 9 This is the Phind 2 client. It is a Java applet, you 10 will need to embed it in a web page with code like the 11 following, and at thew same time run a phind server 12 to provide the phrase information. 1 /********************************************************************** 2 * 3 * Phind.java -- the Phind java applet 4 * 5 * Copyright 1997-2000 Gordon W. Paynter 6 * Copyright 2000 The New Zealand Digital Library Project 7 * 8 * A component of the Greenstone digital library software 9 * from the New Zealand Digital Library Project at the 10 * University of Waikato, New Zealand. 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * 26 *********************************************************************/ 27 28 29 /********************************************************************* 30 31 This applet should be embedded in a web page. For example: 32 13 33 14 34 <APPLET CODE="Phind.class" WIDTH=500 HEIGHT=600> 35 <PARAM NAME=phindcgi VALUE="http://www.nzdl.org/cgi-bin/phindcgi"> 36 <PARAM NAME=library VALUE="http://www.nzdl.org/cgi-bin/library"> 37 <PARAM NAME=collection VALUE="fao.org"> 15 38 <PARAM NAME=orientation VALUE="vertical"> 16 <PARAM NAME=depth VALUE="2"> 17 <PARAM NAME=background VALUE="on"> 18 <PARAM NAME=fontsize VALUE="12"> 19 <PARAM NAME=collection VALUE="small"> 20 <PARAM NAME=server VALUE="dna.stanford.edu"> 21 <PARAM NAME=port VALUE="3000"> 22 <PARAM NAME=search_url VALUE=""> 23 The Phind java Applet 39 <PARAM NAME=depth VALUE="2"> 40 <PARAM NAME=fontsize VALUE="12"> 41 <PARAM NAME=blocksize VALUE="10"> 42 The Phind java applet. 24 43 </APPLET> 25 44 26 27 Classes: 28 29 Phind is the main applet class, it also handles socket connections. 30 ResultDisplay is a Panel that sits in the applet and displays 31 things; displays are connected in a doubly-linked list. 32 ResultBox holds the results of a query. Result boxes are shown 33 to the user through ResultDisplays. Another doubly-linked list. 34 ResultCanvas is what a ResultBox's data is drawn on, and does 35 the painting in ResultCanvas windows. Also handles clicks. 36 ResultItem represents a single result object (a phrase or document). 37 PhindTitle is a canvas used for drawing backgrops in empty Displays. 38 39 40 Applet history: 41 42 2.0 The first Applet, see Witten et al (1999) in JODL. 43 2.1 Interaction with server changed to launch documents. 44 2.2 Thesaurus-style layouts with window titles. 45 This version created for the FAO people. 46 2.2.1 Dec 1, 1999. Ignore clicks that occur within 1 second to 47 prevent lag problems from the FAO. 48 */ 45 The applet comprises several classes: 46 47 1. Phind (this file) is the applet class, loaded by the browser. 48 It also handles network connections. 49 2. ResultDisplay is a Panel that sits in the applet and displays 50 things; displays are connected in a doubly-linked list. 51 3. ResultBox holds the results of a query. Result boxes are shown 52 to the user through ResultDisplays. Another doubly-linked list. 53 4. ResultCanvas is what a ResultBox's data is drawn on, and does 54 the painting in ResultCanvas windows. Also handles clicks. 55 5. ResultItem represents a single result object (a phrase or document). 56 6. PhindTitle is a canvas used for drawing backgrops in empty Displays. 57 58 **********************************************************************/ 49 59 50 60 … … 64 74 import java.awt.TextField; 65 75 76 import java.net.URL; 77 import java.io.DataInputStream; 78 66 79 import java.net.Socket; 67 80 import java.net.InetAddress; … … 76 89 77 90 public class Phind extends java.applet.Applet { 78 79 // elements of the page 80 Label titleLabel; 81 TextField wordField; 82 Choice libraryMenu, swlMenu, lfcMenu, stemMenu; 83 Button searchButton; 84 85 Button prevButton, nextButton; 86 87 // Appearance parameters 88 public boolean showImage; 89 public boolean vertical; 90 public int depth; 91 public int fontSize; 92 public Image backgroundImage; 93 public Font plainFont, boldFont; 94 95 // the downloaded data 96 Panel resultPanel; 97 PhindTitle title; 98 ResultDisplay firstDisplay, lastDisplay; 99 100 // the mode of operation 101 int mode; 102 final int initMode = 0; 103 final int idleMode = 1; 104 final int searchMode = 2; 105 106 // what to search for 107 int phraseBlockSize = 20; 108 int stopwordLevel = 1; 109 int lowFrequencyCutoff = 0; 110 int stemming = 0; 111 String collection; 112 113 // where to search 114 Socket connection; 115 String server, port; 116 String search_url; 117 118 // The time at which the last query finished 119 Date lastQueryEndTime; 120 // This is stored to ensure a 1 second gap between 121 // a query returning and a new one beginning. 122 // It is needed because the FAO folks in Rome have 123 // a huge lag, and frquently click several times 124 // while they wait; these clicks are turned into 125 // new queries, which they await again. 126 // It is no elegant solution, but it seems like 127 // the easiest, given that I don't know threads. 128 // 1. The search button is easy to disable, and is 129 // disabled when a socket connection is in progress. 130 // 2. ResutCanvas widgets can'r be similarly disabled 131 // because the browser hides or wipes them, which 132 // looks very bad. 133 // 3. I cannot just ignore clicks on canvasses because 134 // the browser caches the clicks while the socket connection is 135 // going on, and then sends them through afterwards, when the 136 // canvas is accepting clicks again. 137 // 4. Current sequence of events is to record the time 138 // the last query ends, then whenever a click happens 139 // make sure a second has past. if you double-click the 140 // the first query is sent, returns, end-tie is set, and 141 // the second (and any others made during query time) 142 // is *immediately* processed, but since 1 second 143 // hasn't past it is ignored. 144 145 // browser details 146 String localHost; 91 92 // elements of the page 93 Label titleLabel; 94 TextField wordField; 95 Button searchButton, prevButton, nextButton; 96 97 // Appearance parameters 98 public boolean vertical; 99 public int depth; 100 public int fontSize; 101 public Font plainFont, boldFont; 102 103 // Do we want a background image in the applet? 104 public boolean showImage; 105 public Image backgroundImage; 106 107 // Holders for the downloaded data 108 Panel resultPanel; 109 PhindTitle title; 110 ResultDisplay firstDisplay, lastDisplay; 111 112 // the mode of operation 113 int mode; 114 final int initMode = 0; 115 final int idleMode = 1; 116 final int searchMode = 2; 117 118 // what to search for 119 String collection; 120 int phraseBlockSize; 121 122 //int stopwordLevel = 1; 123 //int lowFrequencyCutoff = 0; 124 //int stemming = 0; 125 126 // where to search 127 Socket connection; 128 String library_address, phindcgi_address; 129 URL library, phindcgi; 130 131 String search_url; 132 133 // browser details 134 String localHost; 135 136 // The time at which the last query finished 137 Date lastQueryEndTime; 138 139 // lastQueryEndTime is stored to ensure a 1 second gap between a query 140 // returning and a new one beginning. It is needed because the FAO 141 // folks in Rome have a huge lag, and frquently click several times 142 // while they wait; these clicks are turned into new queries, which 143 // they await again. It is no elegant solution, but it seems like the 144 // easiest, given that I don't know threads. 145 // 1. The search button is easy to disable, and is disabled when a 146 // socket connection is in progress. 147 // 2. ResutCanvas widgets can'r be similarly disabled because the 148 // browser hides or wipes them, which looks very bad. 149 // 3. I cannot just ignore clicks on canvasses because the browser 150 // caches the clicks while the socket connection is going on, and then 151 // sends them through afterwards, when the canvas is accepting clicks 152 // again. 153 // 4. Current sequence of events is to record the time the last query 154 // ends, then whenever a click happens make sure a second has past. if 155 // you double-click the the first query is sent, returns, end-tie is 156 // set, and the second (and any others made during query time) is 157 // *immediately* processed, but since 1 second hasn't past it is 158 // ignored. 147 159 148 160 149 150 public String getAppletInfo() { 151 return "Phind version 2.2 by Gordon Paynter ([email protected]). Copyright 1997."; 152 } 153 154 public void init() { 155 156 // default search variable values 157 mode = initMode; 158 lastQueryEndTime = new Date(); 159 160 // What is this collection called? 161 collection = new String(getParameter("collection")); 162 System.out.println("Phind collection: " + collection); 163 164 // What server and port do we conect to? 165 server = new String(getParameter("server")); 166 port = new String(getParameter("port")); 167 System.out.println("Phind server: " + server + ", port: " + port); 168 169 // Is there a search URL for this collection? 170 search_url = new String(getParameter("search_url")); 171 System.out.println("Phind search URL: " + search_url); 172 173 // Are the windows arranged vertically or horizontally 174 if (getParameter("orientation").toLowerCase().startsWith("h")) { 175 vertical = false; 176 System.out.println("Phind orientation: horizontal"); 177 } else { 178 System.out.println("Phind orientation: vertical"); 179 vertical = true; 180 } 181 182 // How many phind windows are there? 183 Integer temp; 184 try { 185 temp = Integer.valueOf(getParameter("depth")); 186 depth = temp.intValue(); 187 } catch (Exception e) { 188 temp = null; 189 depth = 3; 190 } 191 System.out.println("Phind depth: " + depth); 192 193 // How many phrases should we fetch at any given time? 194 try { 195 temp = Integer.valueOf(getParameter("blockSize")); 196 phraseBlockSize = temp.intValue(); 197 } catch (Exception e) { 198 temp = null; 199 phraseBlockSize = 10; 200 } 201 System.out.println("Phind phrase block size: " + phraseBlockSize); 202 203 // Should we display a background image? 204 if (getParameter("background").toLowerCase().equals("off")) { 205 showImage = false; 206 System.out.println("Phind background: off"); 207 } else { 208 showImage = true; 209 System.out.println("Phind background: on"); 210 } 211 212 // How large should the font be? 213 try { 214 temp = Integer.valueOf(getParameter("fontsize")); 215 fontSize = temp.intValue(); 216 } catch (Exception e) { 217 temp = null; 218 fontSize = 12; 219 } 220 System.out.println("Phind font size: " + fontSize); 221 222 223 // browser details 224 try { 225 localHost = InetAddress.getLocalHost().toString(); 226 } catch (Exception e) { 227 localHost = "Can't get client host."; 228 } 229 System.out.println("Phind client: " + localHost); 230 System.out.println(""); 231 232 233 // The phind applet layout manager 234 setLayout(new BorderLayout()); 235 236 // the Phind title window 237 if (showImage) backgroundImage = getImage(getCodeBase(), "sequitur.jpg"); 238 title = new PhindTitle(this, true); 239 240 // initialise the user interface 241 setBackground(Color.white); 242 plainFont = new Font("Helvetica", Font.PLAIN, fontSize); 243 boldFont = new Font("Helvetica", Font.BOLD, fontSize); 244 245 // the main Result area 246 // the Panel containing the displays is in the center of the display 247 resultPanel = new Panel(); 248 if (vertical) { 249 resultPanel.setLayout(new GridLayout(depth,1,0,2)); 250 } else { 251 System.out.println("horizontal"); 252 resultPanel.setLayout(new GridLayout(1,depth,2,0)); 253 } 254 add("Center", resultPanel); 255 256 // Create ResultDisplays and place in the interface 257 ResultDisplay d1, d2 = null; 258 firstDisplay = new ResultDisplay(this, null); 259 resultPanel.add(firstDisplay); 260 261 d1 = firstDisplay; 262 for (int i = 2; i <= depth; i++) { 263 d2 = new ResultDisplay(this, d1); 264 resultPanel.add(d2); 265 d1 = d2; 266 } 161 public String getAppletInfo() { 162 return "Phind by Gordon Paynter ([email protected]). Copyright 1997-2000."; 163 } 164 165 public void init() { 166 167 // default search variable values 168 mode = initMode; 169 lastQueryEndTime = new Date(); 170 171 // What is this collection called? 172 try { 173 collection = new String(getParameter("collection")); 174 } catch (Exception e) { 175 System.err.println("Phind: You must specify a collection."); 176 stop(); 177 } 178 System.out.println("Phind collection: " + collection); 179 180 // Where do we get the phind data 181 try { 182 phindcgi_address = new String(getParameter("phindcgi")); 183 } catch (Exception e) { 184 System.err.println("Phind: You must specify a URL for phindcgi."); 185 stop(); 186 } 187 System.out.println("Phind phindcgi: " + phindcgi_address); 188 189 // Where is the collection served from 190 try { 191 library_address = new String(getParameter("library")); 192 } catch (Exception e) { 193 System.err.println("Phind: You must specify a URL for library."); 194 stop(); 195 } 196 System.out.println("Phind library: " + library_address); 197 198 // Is there a search URL for this collection? 199 try { 200 search_url = new String(getParameter("search_url")); 201 System.out.println("Phind search URL: " + search_url); 202 } catch (Exception e) { 203 System.out.println("Phind search_url not set."); 204 } 205 206 // Are the windows arranged vertically or horizontally 207 vertical = true; 208 try { 209 if (getParameter("orientation").toLowerCase().startsWith("h")) { 210 vertical = false; 211 System.out.println("Phind orientation: horizontal"); 212 } 213 } catch (Exception e) { 214 System.out.println("Phind orientation: vertical"); 215 } 216 217 // How many phind windows are there? 218 Integer temp; 219 try { 220 temp = Integer.valueOf(getParameter("depth")); 221 depth = temp.intValue(); 222 } catch (Exception e) { 223 temp = null; 224 depth = 3; 225 } 226 System.out.println("Phind depth: " + depth); 227 228 // How many phrases should we fetch at any given time? 229 try { 230 temp = Integer.valueOf(getParameter("blocksize")); 231 phraseBlockSize = temp.intValue(); 232 } catch (Exception e) { 233 temp = null; 234 phraseBlockSize = 10; 235 } 236 System.out.println("Phind phrase block size: " + phraseBlockSize); 237 238 // Should we display a background image? 239 showImage = false; 240 try { 241 if (getParameter("background").toLowerCase().equals("on")) { 242 showImage = true; 243 System.out.println("Phind background: on"); 244 } 245 } catch (Exception e) { 246 System.out.println("Phind background: off"); 247 } 248 249 250 // How large should the font be? 251 try { 252 temp = Integer.valueOf(getParameter("fontsize")); 253 fontSize = temp.intValue(); 254 } catch (Exception e) { 255 temp = null; 256 fontSize = 12; 257 } 258 System.out.println("Phind font size: " + fontSize); 259 260 // browser details 261 try { 262 localHost = InetAddress.getLocalHost().toString(); 263 } catch (Exception e) { 264 localHost = "Can't get client host."; 265 } 266 System.out.println("Phind client: " + localHost); 267 System.out.println(""); 268 269 // The phind applet layout manager 270 setLayout(new BorderLayout()); 271 272 // the Phind title window 273 if (showImage) backgroundImage = getImage(getCodeBase(), "sequitur.jpg"); 274 title = new PhindTitle(this, true); 275 276 // initialise the user interface 277 setBackground(Color.white); 278 plainFont = new Font("Helvetica", Font.PLAIN, fontSize); 279 boldFont = new Font("Helvetica", Font.BOLD, fontSize); 280 281 // the main Result area 282 283 // the Panel containing the displays is in the center of the display 284 resultPanel = new Panel(); 285 if (vertical) { 286 resultPanel.setLayout(new GridLayout(depth,1,0,2)); 287 } else { 288 System.out.println("horizontal"); 289 resultPanel.setLayout(new GridLayout(1,depth,2,0)); 290 } 291 add("Center", resultPanel); 292 293 // Create ResultDisplays and place in the interface 294 ResultDisplay d1, d2 = null; 295 firstDisplay = new ResultDisplay(this, null); 296 resultPanel.add(firstDisplay); 297 298 d1 = firstDisplay; 299 for (int i = 2; i <= depth; i++) { 300 d2 = new ResultDisplay(this, d1); 301 resultPanel.add(d2); 302 d1 = d2; 303 } 267 304 268 lastDisplay = d2; 269 270 271 // The control panel 272 Panel p1 = new Panel(); 273 add("North", p1); 274 p1.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); 275 276 searchButton = new Button("Search"); 277 searchButton.setFont(boldFont); 278 p1.add(searchButton); 279 280 Label tempLabel = new Label(" for"); 281 tempLabel.setFont(boldFont); 282 p1.add(tempLabel); 283 284 wordField = new TextField(12); 285 wordField.setFont(boldFont); 286 p1.add(wordField); 287 288 Label temp2 = new Label(" "); 289 p1.add(temp2); 290 291 prevButton = new Button("Previous"); 292 prevButton.setFont(boldFont); 293 prevButton.disable(); 294 p1.add(prevButton); 295 296 nextButton = new Button(" Next "); 297 nextButton.setFont(boldFont); 298 nextButton.disable(); 299 p1.add(nextButton); 300 301 302 //swlMenu = new Choice(); 303 //swlMenu.addItem("no stopwords"); 304 //swlMenu.addItem("100 stopwords"); 305 //swlMenu.addItem("200 stopwords"); 306 //swlMenu.addItem("300 stopwords"); 307 //swlMenu.addItem("400 stopwords"); 308 //swlMenu.addItem("500 stopwords"); 309 //swlMenu.select(stopwordLevel); 310 311 //lfcMenu = new Choice(); 312 //lfcMenu.addItem("show all phrases"); 313 //lfcMenu.addItem("hide terminal phrases"); 314 //lfcMenu.addItem("phrase frequency > 2"); 315 //lfcMenu.addItem("phrase frequency > 3"); 316 //lfcMenu.addItem("phrase frequency > 4"); 317 //lfcMenu.addItem("phrase frequency > 5"); 318 //lfcMenu.select(lowFrequencyCutoff); 319 320 //stemMenu = new Choice(); 321 //stemMenu.addItem("no stemming"); 322 //stemMenu.addItem("stemming"); 323 //stemMenu.select(stemming); 324 325 326 // lets get started then 327 setStatus("Welcome to Phind."); 328 mode = idleMode; 329 } 330 331 332 void setStatus(String status) { 333 showStatus(status); 334 } 335 336 public boolean action(Event evt, Object arg) { 337 338 if (evt.target == searchButton) { 339 searchForWord(); 340 } else if (evt.target == wordField) { 341 searchForWord(); 342 } else if (evt.target == prevButton) { 343 shiftPrevious(); 344 } else if (evt.target == nextButton) { 345 shiftNext(); 346 } else { 347 System.out.println("unknown action: " + evt.toString() + ", object: " + arg.toString()); 348 } 349 return true; 350 } 351 352 353 // Search for a word 354 // 355 // called when the "Search" Button is pressed 356 void searchForWord() { 357 358 if (mode == idleMode) { 359 360 // transform the word to an appropriate search key 361 String searchWord = wordField.getText().trim().toLowerCase(); 362 for (int i = 0; i < searchWord.length(); i++) { 363 if ((searchWord.charAt(i) < 'a') || (searchWord.charAt(i) > 'z')) { 364 searchWord = searchWord.substring(0, i); 365 } 366 } 367 wordField.setText(searchWord); 368 369 // look up the word 370 if (searchWord.length() > 1) { 371 setStatus("searching for \"" + searchWord + "\""); 372 firstDisplay.emptyContents(); 373 ResultBox result = lookupPhraseOnServer(null, searchWord, searchWord, 2); 374 375 // if there is an error, return 376 if (result == null) { 377 setStatus("No results for \"" + searchWord + "\""); 378 return; 379 } 380 381 // display the result 382 result.display = firstDisplay.display(result); 383 result.resize(result.display.size()); 384 result.paintAll(result.getGraphics()); 385 } 386 387 enablePreviousAndNext(); 388 } 389 } 305 lastDisplay = d2; 306 307 308 // The "control panel" 309 Panel p1 = new Panel(); 310 add("North", p1); 311 p1.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); 312 313 searchButton = new Button("Search"); 314 searchButton.setFont(boldFont); 315 p1.add(searchButton); 316 317 Label tempLabel = new Label(" for"); 318 tempLabel.setFont(boldFont); 319 p1.add(tempLabel); 320 321 wordField = new TextField(12); 322 wordField.setFont(boldFont); 323 p1.add(wordField); 324 325 Label temp2 = new Label(" "); 326 p1.add(temp2); 327 328 prevButton = new Button("Previous"); 329 prevButton.setFont(boldFont); 330 prevButton.disable(); 331 p1.add(prevButton); 332 333 nextButton = new Button(" Next "); 334 nextButton.setFont(boldFont); 335 nextButton.disable(); 336 p1.add(nextButton); 337 338 // lets get started then 339 setStatus("Welcome to Phind."); 340 mode = idleMode; 341 } 342 343 344 void setStatus(String status) { 345 showStatus(status); 346 } 347 348 public boolean action(Event evt, Object arg) { 349 350 if (evt.target == searchButton) { 351 searchForWord(); 352 } else if (evt.target == wordField) { 353 searchForWord(); 354 } else if (evt.target == prevButton) { 355 shiftPrevious(); 356 } else if (evt.target == nextButton) { 357 shiftNext(); 358 } else { 359 System.out.println("unknown action: " + evt.toString() + ", object: " + arg.toString()); 360 } 361 return true; 362 } 363 364 365 // Search for a word 366 // 367 // called when the "Search" Button is pressed 368 void searchForWord() { 369 370 if (mode == idleMode) { 371 372 // transform the word to an appropriate search key 373 String searchWord = wordField.getText().trim().toLowerCase(); 374 for (int i = 0; i < searchWord.length(); i++) { 375 if ((searchWord.charAt(i) < 'a') || (searchWord.charAt(i) > 'z')) { 376 searchWord = searchWord.substring(0, i); 377 } 378 } 379 wordField.setText(searchWord); 380 381 // look up the word 382 if (searchWord.length() > 1) { 383 setStatus("searching for \"" + searchWord + "\""); 384 firstDisplay.emptyContents(); 385 ResultBox result = lookupPhraseOnServer(null, false, searchWord, searchWord, 2); 386 387 // if there is an error, return 388 if (result == null) { 389 setStatus("No results for \"" + searchWord + "\""); 390 return; 391 } 392 393 // display the result 394 result.display = firstDisplay.display(result); 395 result.resize(result.display.size()); 396 result.paintAll(result.getGraphics()); 397 } 398 399 enablePreviousAndNext(); 400 } 401 } 390 402 391 403 392 // Search for a phrase 393 // 394 // If querymode is 2, the user has clicked on a phrase. 395 // If querymode is 3, the user has requested more phrases. 396 // If querymode is 4, the user has requested more documents. 397 void searchForPhrase(ResultBox source, String key, String phrase, int queryMode) { 398 399 // System.out.println("searchForPhrase: " + key + " " + phrase + " " + queryMode); 400 401 if (mode == idleMode) { 402 403 // If we are going to replace the next ResultDisplay, then empty it 404 if (queryMode <= 2) { 405 if (source.display.next != null) source.display.next.emptyContents(); 406 } 407 408 // look up the word 409 setStatus("Searching for \"" + phrase + "\""); 410 ResultBox result = lookupPhraseOnServer(source, key, phrase, queryMode); 411 if (result == null) { 412 setStatus("No result for \"" + phrase + "\""); 413 return; 414 } 415 416 // If this is not already displayed, display it in the last free spot 417 if (queryMode <= 2) { 418 result.display = lastDisplay.display(result); 419 result.resize(result.display.size()); 420 result.paintAll(result.getGraphics()); 421 } 422 423 enablePreviousAndNext(); 424 } 425 } 426 427 428 // Look up a phrase (or symbol) on the server 429 // 430 // Arguments are the source of the query (a ResultBox, or null if the 431 // query comes from hitting the search button), the key to search for 432 // (the text of a phrase or a symbol number), the phrase as a string, 433 // and the query mode. 434 // Query modes are: 435 // 0 = get all phrases with LFC, 436 // 1 = get all URLs with LFC, 437 // 2 = get first N phrases and URLs, 438 // 3 = get another N phrases into same window 439 // 4 = get another N documents into same window 440 441 ResultBox lookupPhraseOnServer(ResultBox source, String key, String phrase, int queryMode) { 404 // Search for a phrase 405 // 406 // If querymode is 2, the user has clicked on a phrase. 407 // If querymode is 3, the user has requested more phrases. 408 // If querymode is 4, the user has requested more documents. 409 void searchForPhrase(ResultBox source, String key, String phrase, int queryMode) { 410 411 // System.out.println("searchForPhrase: " + key + " " + phrase + " " + queryMode); 412 413 if (mode == idleMode) { 414 415 // If we are going to replace the next ResultDisplay, then empty it 416 if (queryMode <= 2) { 417 if (source.display.next != null) source.display.next.emptyContents(); 418 } 419 420 // look up the word 421 setStatus("Searching for \"" + phrase + "\""); 422 ResultBox result = lookupPhraseOnServer(source, true, key, phrase, queryMode); 423 if (result == null) { 424 setStatus("No result for \"" + phrase + "\""); 425 return; 426 } 427 428 // If this is not already displayed, display it in the last free spot 429 if (queryMode <= 2) { 430 result.display = lastDisplay.display(result); 431 result.resize(result.display.size()); 432 result.paintAll(result.getGraphics()); 433 } 434 435 enablePreviousAndNext(); 436 } 437 } 438 439 440 // Look up a phrase (or symbol) on the server 441 // 442 // Arguments are the source of the query (a ResultBox, or null if the 443 // query comes from hitting the search button), the key to search for 444 // (the text of a phrase or a symbol number), the phrase as a string, 445 // and the query mode. 446 // Query modes are: 447 // 0 = obsolete 448 // 1 = obsolete 449 // 2 = get first N phrases and URLs, 450 // 3 = get another N phrases into same window 451 // 4 = get another N documents into same window 452 453 ResultBox lookupPhraseOnServer(ResultBox source, 454 boolean keyKnown, String key, String phrase, 455 int queryMode) { 456 searchButton.disable(); 457 mode = searchMode; 458 ResultBox r = null; 459 460 if (queryMode <= 2) { 461 r = new ResultBox(this, collection, key, phrase, source); 462 } else if ((queryMode == 3) || (queryMode == 4)) { 463 r = source; 464 } 465 466 try { 467 queryServer(keyKnown, key, queryMode, r); 468 } catch (Exception e) { 469 System.out.println("Phind query error: " + e.toString()); 470 setStatus("Query error: " + e.toString()); 471 mode = idleMode; 472 searchButton.enable(); 473 return null; 474 } 475 476 // The query is finished 477 setStatus(r.c.numberOfPhrases + " results containing \"" + phrase + "\""); 478 mode = idleMode; 479 searchButton.enable(); 480 lastQueryEndTime = new Date(); 481 482 return r; 483 } 484 485 486 // Query the phindcgi program 487 // 488 // Send a query (a word or symbol number) to the server 489 // Open a socket connection to the server, send it a query, 490 // and pass the result to a ResultBox. 491 492 void queryServer(boolean keyKnown, String word, int queryMode, ResultBox area) 493 throws IOException { 494 495 // Set up connections (streams) 496 //connection = new Socket(server, Integer.parseInt(port)); 497 //OutputStream out = connection.getOutputStream(); 498 //InputStream in = connection.getInputStream(); 499 500 // Build the query 501 String query = phindcgi_address + "?x=1&c=" + collection; 502 503 if (keyKnown) { 504 query = query + "&n=" + word; 505 } else { 506 query = query + "&p=" + word; 507 } 508 509 // Specify the number of results to return and the first and last results. 510 if (queryMode <= 2) { 511 query = query + "&f=0&d=" + phraseBlockSize + "&g=0&e=" + phraseBlockSize; 512 } else if (queryMode == 3) { 513 // Add phrases to an existing result set. 514 query = query + "&f=0&d=" + phraseBlockSize + "&g=0&e=" + phraseBlockSize; 515 // query = (word + " " + queryMode + " " + phraseBlockSize + " " + area.nextPhraseBlock); 516 area.nextPhraseBlock++; 517 } else if (queryMode == 4) { 518 // Add documents to existing result set. 519 query = query + "&f=0&d=" + phraseBlockSize + "&g=0&e=" + phraseBlockSize; 520 // query = (word + " " + queryMode + " " + phraseBlockSize + " " + area.nextDocumentBlock); 521 area.nextDocumentBlock++; 522 } 523 524 525 // Send the query to the phindcgi program 526 System.out.println("sending query: " + query); 527 try { 528 phindcgi = new URL(query); 529 DataInputStream in = new DataInputStream(phindcgi.openStream()); 530 byte[] buffer; 531 int availableBytes = 0; 532 533 while (!area.finished) { 534 availableBytes = in.available(); 535 if (availableBytes == 0) { 536 // if i had threads i'd do a wait here for 1 second 537 } else { 538 buffer = new byte[availableBytes]; 539 in.read(buffer); 540 area.parseBytes(buffer); 541 } 542 } 543 544 in.close(); 545 } catch (Exception e) { 546 System.err.println( "Error sending query to phindcgi: " + e); 547 } 548 area.repaint(); 549 } 442 550 443 searchButton.disable(); 444 mode = searchMode; 445 ResultBox r = null; 446 447 if (queryMode <= 2) { 448 r = new ResultBox(this, collection, 449 key, phrase, stopwordLevel, lowFrequencyCutoff, source); 450 // area.resetBox(); 451 } else if ((queryMode == 3) || (queryMode == 4)) { 452 r = source; 453 } 454 455 try { 456 queryServer(key, queryMode, r); 457 } catch (Exception e) { 458 System.out.println("Phind socket exception error: " + e.toString()); 459 setStatus("Socket error: " + e.toString()); 460 mode = idleMode; 461 searchButton.enable(); 462 return null; 463 } 464 465 // The query is finished 466 setStatus(r.c.numberOfPhrases + " results containing \"" + phrase + "\""); 467 mode = idleMode; 468 searchButton.enable(); 469 lastQueryEndTime = new Date(); 470 // System.out.println("Query end time: " + lastQueryEndTime.toString()); 471 472 return r; 473 } 474 475 // Send a query (a word or symbol number) to the server 476 // Open a socket connection to the server, send it a query, 477 // and pass the result to a ResultBox. 478 void queryServer( String word, int queryMode, ResultBox area ) throws IOException { 479 480 // Set up connections (streams) 481 connection = new Socket(server, Integer.parseInt(port)); 482 OutputStream out = connection.getOutputStream(); 483 InputStream in = connection.getInputStream(); 484 485 // Build the query 486 String query = ""; 487 if (queryMode < 2) { 488 // Specify the LFC and whether to use stemming 489 query = (word + " " + queryMode + " " + lowFrequencyCutoff + " " + stemming); 490 } else if (queryMode == 2) { 491 // Specify the number of results to return and 492 // the result set number. 493 query = (word + " " + queryMode + " " + phraseBlockSize + " 0"); 494 } else if (queryMode == 3) { 495 // The user is adding another 100 (or so) phrases to an 496 // existing result set. 497 query = (word + " " + queryMode + " " + phraseBlockSize + " " + area.nextPhraseBlock); 498 area.nextPhraseBlock++; 499 } else if (queryMode == 4) { 500 // Add documents to existing result set. 501 query = (word + " " + queryMode + " " + phraseBlockSize + " " + area.nextDocumentBlock); 502 area.nextDocumentBlock++; 503 } 504 505 // Add a comment identifying the host to the query 506 query = (query + " # " + localHost); 507 508 509 // System.out.println("sending query: " + query); 510 511 // Send the query 512 char searchChars[] = query.toCharArray(); 513 byte searchBytes[] = new byte[searchChars.length + 1]; 514 for (int i = 0; i < searchChars.length; i++) 515 searchBytes[i] = (byte) searchChars[i]; 516 searchBytes[searchChars.length] = ((byte) '\n'); 517 out.write(searchBytes); 518 519 // Read the response 520 int maxBytes = 1000; 521 int availableBytes = 0; 522 byte[] buffer; 523 boolean reachedDONE = false; 524 525 while (!reachedDONE) { 526 // System.out.print("reading: " + in.available()); 527 availableBytes = in.available(); 528 if (availableBytes == 0) { 529 // if i had threads i'd do a wait here for 1 second 530 } else { 531 buffer = new byte[availableBytes]; 532 in.read(buffer); 533 area.parseBytes(buffer); 534 reachedDONE = area.finished; 535 } 536 } 537 538 area.repaint(); 539 connection.close(); 540 } 541 542 543 // Previous and Next functionality 544 545 // enable or disable the "Previous" and "Next" buttons 546 void enablePreviousAndNext() { 547 548 Component c = firstDisplay.current; 549 if (c.getClass().getName().equals("ResultBox")) { 550 if (((ResultBox) c).prevBoxExists()) { 551 prevButton.enable(); 552 } else { 553 prevButton.disable(); 554 } 555 } 556 557 c = lastDisplay.current; 558 if (c.getClass().getName().equals("ResultBox")) { 559 if (((ResultBox) c).nextBoxExists()) { 560 nextButton.enable(); 561 } else { 562 nextButton.disable(); 563 } 564 } 565 } 566 567 // Shift to previous box 568 // 569 // If the user clicks "Previous" then scroll up. 570 void shiftPrevious() { 571 572 Component c = firstDisplay.current; 573 if (c.getClass().getName().equals("ResultBox")) { 574 575 ResultBox b = (ResultBox) c; 576 if (b.prevBoxExists()) { 577 b = b.prev; 578 579 // empty all the displays 580 firstDisplay.emptyContents(); 581 582 // add as many result boxes as there are displays 583 for (int i = 1 ; ((i <= depth) && (b != null)); i++) { 584 lastDisplay.display(b); 585 b.resize(b.display.size()); 586 b.paintAll(b.getGraphics()); 587 b = b.next; 588 } 589 } 590 } 591 enablePreviousAndNext(); 592 } 593 594 595 // Shift to next box 596 // 597 // If the user clicks "Next" then scroll down if possible 598 void shiftNext() { 599 600 Component c = lastDisplay.current; 601 if (c.getClass().getName().equals("ResultBox")) { 602 603 ResultBox b = (ResultBox) c; 604 if (b.nextBoxExists()) { 605 606 // find the new "first" displayed box 607 c = firstDisplay.current; 608 b = (ResultBox) c; 609 b = b.next; 610 611 // empty all the displays 612 firstDisplay.emptyContents(); 613 614 // add as many result boxes as there are displays 615 for (int i = 1 ; ((i <= depth) && (b != null)); i++) { 616 lastDisplay.display(b); 617 b.resize(b.display.size()); 618 b.paintAll(b.getGraphics()); 619 b = b.next; 620 } 621 } 622 } 623 enablePreviousAndNext(); 624 } 551 552 // Previous and Next button functionality 553 554 // enable or disable the "Previous" and "Next" buttons 555 void enablePreviousAndNext() { 556 557 Component c = firstDisplay.current; 558 if (c.getClass().getName().equals("ResultBox")) { 559 if (((ResultBox) c).prevBoxExists()) { 560 prevButton.enable(); 561 } else { 562 prevButton.disable(); 563 } 564 } 565 566 c = lastDisplay.current; 567 if (c.getClass().getName().equals("ResultBox")) { 568 if (((ResultBox) c).nextBoxExists()) { 569 nextButton.enable(); 570 } else { 571 nextButton.disable(); 572 } 573 } 574 } 575 576 // Shift to previous box 577 // 578 // If the user clicks "Previous" then scroll up. 579 void shiftPrevious() { 580 581 Component c = firstDisplay.current; 582 if (c.getClass().getName().equals("ResultBox")) { 583 584 ResultBox b = (ResultBox) c; 585 if (b.prevBoxExists()) { 586 b = b.prev; 587 588 // empty all the displays 589 firstDisplay.emptyContents(); 590 591 // add as many result boxes as there are displays 592 for (int i = 1 ; ((i <= depth) && (b != null)); i++) { 593 lastDisplay.display(b); 594 b.resize(b.display.size()); 595 b.paintAll(b.getGraphics()); 596 b = b.next; 597 } 598 } 599 } 600 enablePreviousAndNext(); 601 } 602 603 604 // Shift to next box 605 // 606 // If the user clicks "Next" then scroll down if possible 607 void shiftNext() { 608 609 Component c = lastDisplay.current; 610 if (c.getClass().getName().equals("ResultBox")) { 611 612 ResultBox b = (ResultBox) c; 613 if (b.nextBoxExists()) { 614 615 // find the new "first" displayed box 616 c = firstDisplay.current; 617 b = (ResultBox) c; 618 b = b.next; 619 620 // empty all the displays 621 firstDisplay.emptyContents(); 622 623 // add as many result boxes as there are displays 624 for (int i = 1 ; ((i <= depth) && (b != null)); i++) { 625 lastDisplay.display(b); 626 b.resize(b.display.size()); 627 b.paintAll(b.getGraphics()); 628 b = b.next; 629 } 630 } 631 } 632 enablePreviousAndNext(); 633 } 625 634 626 635 } -
trunk/gsdl/src/phind/client/ResultBox.java
r1621 r1625 1 /********************************************************************** 2 * 3 * ResultBox.java -- a list of phrases in the Phind java interface 4 * 5 * Copyright 1997-2000 Gordon W. Paynter 6 * Copyright 2000 The New Zealand Digital Library Project 7 * 8 * A component of the Greenstone digital library software 9 * from the New Zealand Digital Library Project at the 10 * University of Waikato, New Zealand. 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * 26 *********************************************************************/ 27 28 /********************************************************************* 29 30 This class is used in the Phind java applet (Phind.java). 31 32 A ResultBox holds the results of a query to phindcgi. They deal mostly 33 with the information content of the query, and have methods for parsing the 34 input into phrase and document items. They have little do with display: 35 ResultBoxes are shown to the user through "ResultDisplay" panels, and are 36 drawn using "ResultCanvas" objects. 37 38 **********************************************************************/ 39 40 1 41 import java.awt.Panel; 2 42 import java.awt.BorderLayout; … … 11 51 import java.util.Vector; 12 52 53 13 54 public class ResultBox extends Panel { 14 15 // Other objects at a higher level than this one16 Phind phind;17 ResultDisplay display;18 ResultBox prev, next;19 20 // The objects this one contains21 ResultCanvas c;22 ResultTitle t;23 Scrollbar s;24 Panel label;25 26 // Information about the query27 String searchKey, searchPhrase;28 String searchCollection;29 int searchSWL, searchLFC;30 31 // Information about the result set32 int numberOfExpansions;33 int expansionsRetrieved;34 int numberOfDocuments;35 int documentsRetrieved;36 int nextPhraseBlock;37 int nextDocumentBlock;38 39 // just why did i add these variables?40 int mode;41 final int initMode = 0;42 public final int emptyMode = 1;43 final int loadingMode = 2;44 final int finishedMode = 3;45 46 String buffer;47 boolean finished;48 49 50 // Create a ResultBox51 // given details of the search that generated it.52 ResultBox(Phind p, String collect, String key, String phrase, int swl, int lfc, ResultBox rb) {53 54 super();55 mode = initMode;56 57 phind = p;58 display = null;59 next = null;60 prev = rb;61 if (prev != null) prev.next = this;62 63 numberOfExpansions = -1;64 expansionsRetrieved = 0;65 numberOfDocuments = -1;66 documentsRetrieved = 0;67 nextPhraseBlock = 1;68 nextDocumentBlock = 1;69 70 searchKey = key;71 searchPhrase = phrase;72 searchCollection = collect;73 searchSWL = swl;74 searchLFC = lfc;75 76 setLayout(new BorderLayout());77 78 79 s = new Scrollbar(Scrollbar.VERTICAL);80 disableScrollbar();81 add("East", s);82 83 c = new ResultCanvas(this);84 add("Center", c);85 86 t = new ResultTitle(this);87 add("North", t);88 89 buffer = "";90 finished = false;91 mode = emptyMode;92 }93 94 static String describeContents(String phrase, String c, int swl) {95 return( "\"" +phrase + "\" in " + c + ", swl = " + swl + ".");96 }97 98 String describeContents() {99 return( describeContents(searchPhrase, searchCollection, searchSWL) );100 }101 102 103 // Reset the contents of the box104 void resetBox( ) {105 buffer = "";106 finished = false;107 c.resetCanvas();108 disableScrollbar();109 mode = emptyMode;110 55 111 numberOfExpansions = -1; 112 expansionsRetrieved = 0; 113 numberOfDocuments = -1; 114 documentsRetrieved = 0; 115 } 116 117 void setStatus( String status ) { 118 phind.setStatus(status); 119 } 120 121 void disableScrollbar() { 122 if (s.isEnabled()) { 123 s.setValues(0, 1, 0, 1); 124 s.setLineIncrement(1); 125 s.setPageIncrement(1); 126 s.disable(); 127 } 128 } 129 130 // Are there displays previous to and after this? 131 public boolean prevBoxExists () { 132 return (prev != null); 133 } 134 public boolean nextBoxExists () { 135 return (next != null); 136 } 137 138 139 void lookupPhrase(String key, String phrase, int queryMode) { 140 buffer = ""; 141 finished = false; 142 phind.searchForPhrase(this, key, phrase, queryMode); 143 t.repaint(); 144 } 145 146 public boolean handleEvent(Event event) { 147 // System.out.println("event: " + event.toString()); 148 if ( (event.target == s) && 149 ( (event.id == Event.SCROLL_ABSOLUTE) || 150 (event.id == Event.SCROLL_LINE_DOWN) || 151 (event.id == Event.SCROLL_LINE_UP) || 152 (event.id == Event.SCROLL_PAGE_DOWN) || 153 (event.id == Event.SCROLL_PAGE_UP) ) ) { 154 c.repaint(); 155 return true; 156 } else { 157 return super.handleEvent(event); 158 } 159 } 160 161 162 // a new section of the byte stream is read 163 void parseBytes(byte[] bytes) { 164 mode = loadingMode; 165 166 // update the buffer that holds the bytes read 167 String input = new String(bytes,0); 168 buffer = buffer.concat(input); 169 170 // if buffer ends with "DONE" then we are finished reading 171 finished = buffer.endsWith("DONE\n"); 172 173 // Parse each line until there are no more lines to parse 174 while(parseLine()); 175 176 if (finished) { 177 c.updateMorePhrasesMarker(); 178 c.updateMoreDocumentsMarker(); 179 } else { 180 // We haven't finished, give some feedback about progress 181 setStatus("Connected to host, " + c.numberOfPhrases + " results read"); 182 } 183 } 184 185 // try to sort the buffered bytes into lines and output them 186 // returns true if a full line of text was extracted 187 boolean parseLine() { 188 189 // System.out.println("parseLine " + finished + "(" + expansionsRetrieved + ")"); 190 191 int eol = buffer.indexOf((int) '\n'); 192 if (eol == -1) { 193 return false; 194 195 } else if (buffer.charAt(0) == 'D') { 196 // System.out.println( "parseLine has hit DONE" ); 197 mode = finishedMode; 198 return false; 199 200 } else { 201 String item = buffer.substring(0, eol); 202 buffer = buffer.substring(eol + 1); 203 if (!addLine(item)) { 204 System.out.println( "Error calling addline with: " + item ); 205 } 206 return true; 207 } 208 } 209 210 // add a single line of input. 211 // return true if successful, otherwise false. 212 boolean addLine( String line ) { 213 214 // System.out.println( "addLine: " + line + "(" + expansionsRetrieved + ")"); 215 216 int nextSplit; 217 String ruleStr = "", freqStr = "", expandStr = "", docfStr = "", 218 prefix = "", body = "", suffix = ""; 219 220 // If there is no space on the line, then there is only one number. 221 // This number is the number of results; we can expect two such; 222 // the first is the number of expansions, the second documents 223 nextSplit = line.indexOf((int) ' '); 224 if (nextSplit == -1) { 225 if (numberOfExpansions < 0) { 226 numberOfExpansions = Integer.valueOf(line).intValue(); 227 } else if (numberOfDocuments < 0) { 228 numberOfDocuments = Integer.valueOf(line).intValue(); 229 } 230 return true; 231 } 232 233 // get the rule number 234 ruleStr = line.substring(0, nextSplit); 235 line = line.substring(nextSplit + 1); 236 237 // find the frequency 238 nextSplit = line.indexOf((int) ' '); 239 if (nextSplit == -1) { 240 System.out.println( "Error: can't find a space in:" + line ); 241 return false; 242 } 243 freqStr = line.substring(0, nextSplit); 244 line = line.substring(nextSplit + 1); 56 // Objects at a "higher" level than this one 57 Phind phind; 58 ResultDisplay display; 59 60 // Surroundig objects 61 ResultBox prev, next; 62 63 // The components contained by this one. 64 ResultCanvas c; 65 ResultTitle t; 66 Scrollbar s; 67 Panel label; 68 69 // Information about the query 70 String searchKey, searchPhrase; 71 String searchCollection; 245 72 246 // find the expansion boolean 247 nextSplit = line.indexOf((int) ' '); 248 if (nextSplit == -1) { 249 System.out.println( "Error: can't find second space in: " + line ); 250 return false; 251 } 252 expandStr = line.substring(0, nextSplit); 253 line = line.substring(nextSplit + 1); 254 255 // find the document frequency 256 nextSplit = line.indexOf((int) ' '); 257 if (nextSplit == -1) { 258 System.out.println( "Error: can't find second space in: " + line ); 259 return false; 260 } 261 docfStr = line.substring(0, nextSplit); 262 line = line.substring(nextSplit + 1); 263 264 // find the prefix 265 nextSplit = line.indexOf((int) '<'); 266 if (nextSplit == -1) { 267 System.out.println( "Error: can't find a \"<\" in:" + line ); 268 return false; 269 } 270 prefix = line.substring(0, nextSplit).trim(); 271 line = line.substring(nextSplit + 1); 272 273 // find the body and suffix 274 nextSplit = line.indexOf((int) '>'); 275 if (nextSplit == -1) { 276 System.out.println( "Error: can't find a \">\" in:" + line ); 277 return false; 278 } 279 body = line.substring(0, nextSplit).trim(); 280 suffix = line.substring(nextSplit + 1).trim(); 281 282 // System.out.println( "body: " + body + " - " + suffix); 283 284 ResultItem ri = new ResultItem(ruleStr, freqStr, expandStr, 285 docfStr, prefix, body, suffix); 286 287 if (c.addResultItem(ri)) { 288 if (ri.isPhrase()) { 289 expansionsRetrieved++; 290 } else { 291 documentsRetrieved++; 292 } 293 return true; 294 } else { 295 return false; 296 } 297 } 298 73 // Information about the result set 74 int numberOfExpansions; 75 int expansionsRetrieved; 76 int numberOfDocuments; 77 int documentsRetrieved; 78 int nextPhraseBlock; 79 int nextDocumentBlock; 80 81 // just why did i add these variables? 82 int mode; 83 final int initMode = 0; 84 public final int emptyMode = 1; 85 final int loadingMode = 2; 86 final int finishedMode = 3; 87 88 String buffer; 89 boolean finished; 90 91 92 // Create a ResultBox 93 // given details of the search that generated it. 94 ResultBox(Phind p, String collect, String key, String phrase, ResultBox rb) { 95 96 super(); 97 mode = initMode; 98 99 phind = p; 100 display = null; 101 next = null; 102 prev = rb; 103 if (prev != null) prev.next = this; 104 105 numberOfExpansions = -1; 106 expansionsRetrieved = 0; 107 numberOfDocuments = -1; 108 documentsRetrieved = 0; 109 nextPhraseBlock = 1; 110 nextDocumentBlock = 1; 111 112 searchKey = key; 113 searchPhrase = phrase; 114 searchCollection = collect; 115 116 setLayout(new BorderLayout()); 117 118 119 s = new Scrollbar(Scrollbar.VERTICAL); 120 disableScrollbar(); 121 add("East", s); 122 123 c = new ResultCanvas(this); 124 add("Center", c); 125 126 t = new ResultTitle(this); 127 add("North", t); 128 129 buffer = ""; 130 finished = false; 131 mode = emptyMode; 132 } 133 134 static String describeContents(String phrase, String c) { 135 return( "\"" +phrase + "\" in " + c + "."); 136 } 137 138 String describeContents() { 139 return( describeContents(searchPhrase, searchCollection) ); 140 } 141 142 143 // Reset the contents of the box 144 void resetBox( ) { 145 buffer = ""; 146 finished = false; 147 c.resetCanvas(); 148 disableScrollbar(); 149 mode = emptyMode; 150 151 numberOfExpansions = -1; 152 expansionsRetrieved = 0; 153 numberOfDocuments = -1; 154 documentsRetrieved = 0; 155 } 156 157 void setStatus( String status ) { 158 phind.setStatus(status); 159 } 160 161 void disableScrollbar() { 162 if (s.isEnabled()) { 163 s.setValues(0, 1, 0, 1); 164 s.setLineIncrement(1); 165 s.setPageIncrement(1); 166 s.disable(); 167 } 168 } 169 170 // Are there displays previous to and after this? 171 public boolean prevBoxExists () { 172 return (prev != null); 173 } 174 public boolean nextBoxExists () { 175 return (next != null); 176 } 177 178 179 void lookupPhrase(String key, String phrase, int queryMode) { 180 buffer = ""; 181 finished = false; 182 phind.searchForPhrase(this, key, phrase, queryMode); 183 t.repaint(); 184 } 185 186 public boolean handleEvent(Event event) { 187 // System.out.println("event: " + event.toString()); 188 if ( (event.target == s) && 189 ( (event.id == Event.SCROLL_ABSOLUTE) || 190 (event.id == Event.SCROLL_LINE_DOWN) || 191 (event.id == Event.SCROLL_LINE_UP) || 192 (event.id == Event.SCROLL_PAGE_DOWN) || 193 (event.id == Event.SCROLL_PAGE_UP) ) ) { 194 c.repaint(); 195 return true; 196 } else { 197 return super.handleEvent(event); 198 } 199 } 200 201 202 // a new section of the byte stream is read 203 void parseBytes(byte[] bytes) { 204 mode = loadingMode; 205 206 // update the buffer that holds the bytes read 207 String input; 208 try { 209 input = new String(bytes, new String("Latin1")); 210 } catch (Exception e) { 211 System.err.println(e); 212 input = ""; 213 } 214 buffer = buffer.concat(input); 215 216 // if buffer ends with "</phinddata>" then we are finished reading 217 finished = buffer.endsWith("</phinddata>\n"); 218 219 // Parse each line until there are no more lines to parse 220 while(parseLine()); 221 222 if (finished) { 223 c.updateMorePhrasesMarker(); 224 c.updateMoreDocumentsMarker(); 225 } else { 226 // We haven't finished, give some feedback about progress 227 setStatus("Connected to host, " + c.numberOfPhrases + " results read"); 228 } 229 } 230 231 // Parse a line of XML 232 // 233 // This isn't necessarily real XML. We assume every tag begins and 234 // ends on one line. We read one line out of the buffer at a time, 235 // then "add" them to the box with the addLine method. 236 // 237 // Return true if there is a another line here to parse, otherwise false. 238 239 boolean parseLine() { 240 241 // System.out.println("parseLine " + finished + "(" + expansionsRetrieved + ")"); 242 String item; 243 int eol = buffer.indexOf((int) '\n'); 244 245 // If there are no carriage returns, the line is incomplete 246 if (eol == -1) { 247 return false; 248 } 249 250 // The <phinddata> tag introduces the dataset 251 else if (buffer.startsWith("<phinddata ")) { 252 253 } 254 255 // The <expansionlist> tag 256 else if (buffer.startsWith("<expansionlist ")) { 257 258 } 259 260 // The <expansion> tag 261 else if (buffer.startsWith("<expansion ")) { 262 item = buffer.substring(0, eol); 263 buffer = buffer.substring(eol + 1); 264 addExpansionTag(item); 265 return true; 266 } 267 268 // The <document> tag 269 else if (buffer.startsWith("<document ")) { 270 item = buffer.substring(0, eol); 271 buffer = buffer.substring(eol + 1); 272 addDocumentTag(item); 273 return true; 274 } 275 276 // The <documentlist> tag 277 else if (buffer.startsWith("<documentlist ")) { 278 279 } 280 281 // The </phinddata> tag concludes the dataset 282 else if (buffer.startsWith("</phinddata>")) { 283 mode = finishedMode; 284 return false; 285 } 286 287 // Ignore the piece we've read 288 item = buffer.substring(0, eol); 289 buffer = buffer.substring(eol + 1); 290 return true; 291 } 292 293 294 295 // Add an expansion tag 296 // 297 // Given a string containing an XML expansin tag of the form: 298 // <expansion num="3" id="8421" text="PEOPLE and TREES" tf="3" df="3"/> 299 // <expansion num="4" id="8696" text="FOREST TREES" tf="3" df="3"/> 300 // Create a new ResultItem for display 301 // 302 // Return true if successful, otherwise false. 303 304 boolean addExpansionTag( String line ) { 305 306 // System.out.println( "addExpansionTag: " + line + " (" + expansionsRetrieved + ")"); 307 308 String numStr = "", idStr = "", tfStr = "", dfStr = "", body = ""; 309 310 // Break the tag down into its component parts 311 line = line.substring(11); 312 int nextSplit; 313 while (line.length() > 0) { 314 line = line.trim(); 315 316 // Read the expansion number 317 if (line.startsWith("num")) { 318 line = line.substring(5); 319 nextSplit = line.indexOf((int) '"'); 320 if (nextSplit >= 1) { 321 numStr = line.substring(0, nextSplit); 322 line = line.substring(nextSplit + 1); 323 } else { 324 System.err.println("ResultBox addExpansionTag: error parsing: " + line); 325 } 326 } 327 328 // Read the phrase ID 329 else if (line.startsWith("id")) { 330 line = line.substring(4); 331 nextSplit = line.indexOf((int) '"'); 332 if (nextSplit >= 1) { 333 idStr = line.substring(0, nextSplit); 334 line = line.substring(nextSplit + 1); 335 } else { 336 System.err.println("ResultBox addExpansionTag: error parsing: " + line); 337 } 338 } 339 340 // Read the text of the phrase 341 else if (line.startsWith("text")) { 342 line = line.substring(6); 343 nextSplit = line.indexOf((int) '"'); 344 if (nextSplit >= 1) { 345 body = line.substring(0, nextSplit); 346 line = line.substring(nextSplit + 1); 347 } else { 348 System.err.println("ResultBox addExpansionTag: error parsing: " + line); 349 } 350 } 351 352 // Read the frequency 353 else if (line.startsWith("tf")) { 354 line = line.substring(4); 355 nextSplit = line.indexOf((int) '"'); 356 if (nextSplit >= 1) { 357 tfStr = line.substring(0, nextSplit); 358 line = line.substring(nextSplit + 1); 359 } else { 360 System.err.println("ResultBox addExpansionTag: error parsing: " + line); 361 } 362 } 363 364 // Read the document frequency 365 else if (line.startsWith("df")) { 366 line = line.substring(4); 367 nextSplit = line.indexOf((int) '"'); 368 if (nextSplit >= 1) { 369 dfStr = line.substring(0, nextSplit); 370 line = line.substring(nextSplit + 1); 371 } else { 372 System.err.println("ResultBox addExpansionTag: error parsing: " + line); 373 } 374 } 375 376 // Read some other tag 377 else { 378 nextSplit = line.indexOf((int) ' '); 379 if (nextSplit >= 1) { 380 line = line.substring(nextSplit + 1); 381 } else { 382 line = ""; 383 } 384 } 385 } 386 387 // Create a new ResultItem and add it to the display 388 ResultItem ri = new ResultItem(idStr, tfStr, dfStr, "", body, ""); 389 390 if (c.addResultItem(ri)) { 391 expansionsRetrieved++; 392 return true; 393 } 394 395 return false; 396 } 397 398 399 400 401 // Add an document tag 402 // 403 // Given a string containing an XML document tag of the form: 404 // <document num="2" hash="HASH424e64b811fdad933be69c" freq="1" title="CONTENS"/> 405 // <document num="3" hash="HASH01f08efd8752ad54ca0a99cf" freq="1" title="Tree mixtures"/> 406 // 407 // Create a new ResultItem for display 408 // 409 // Return true if successful, otherwise false. 410 411 boolean addDocumentTag( String line ) { 412 413 System.out.println( "addDocumentTag: " + line + " (" + expansionsRetrieved + ")"); 414 415 String num = "", hash = "", freq = "", title = ""; 416 line = line.substring(9); 417 418 // Break the tag down into its component parts 419 int nextSplit; 420 while (line.length() > 0) { 421 line = line.trim(); 422 423 // Read the expansion number 424 if (line.startsWith("num")) { 425 line = line.substring(5); 426 nextSplit = line.indexOf((int) '"'); 427 if (nextSplit >= 1) { 428 num = line.substring(0, nextSplit); 429 line = line.substring(nextSplit + 1); 430 } else { 431 System.err.println("ResultBox addExpansionTag: error parsing: " + line); 432 } 433 } 434 435 // Read the document OID hash 436 else if (line.startsWith("hash")) { 437 line = line.substring(6); 438 nextSplit = line.indexOf((int) '"'); 439 if (nextSplit >= 1) { 440 hash = line.substring(0, nextSplit); 441 line = line.substring(nextSplit + 1); 442 } else { 443 System.err.println("ResultBox addExpansionTag: error parsing: " + line); 444 } 445 } 446 447 // Read the document frequency 448 else if (line.startsWith("freq")) { 449 line = line.substring(6); 450 nextSplit = line.indexOf((int) '"'); 451 if (nextSplit >= 1) { 452 freq = line.substring(0, nextSplit); 453 line = line.substring(nextSplit + 1); 454 } else { 455 System.err.println("ResultBox addExpansionTag: error parsing: " + line); 456 } 457 } 458 459 // Read the title 460 else if (line.startsWith("title")) { 461 line = line.substring(7); 462 nextSplit = line.indexOf((int) '"'); 463 if (nextSplit >= 1) { 464 title = line.substring(0, nextSplit); 465 line = line.substring(nextSplit + 1); 466 } else { 467 System.err.println("ResultBox addExpansionTag: error parsing: " + line); 468 } 469 } 470 } 471 472 // Create a new ResultItem and add it to the display 473 ResultItem ri = new ResultItem(hash, title, freq); 474 475 if (c.addResultItem(ri)) { 476 documentsRetrieved++; 477 return true; 478 } 479 480 return false; 481 } 299 482 } 300 483 484 485 486 -
trunk/gsdl/src/phind/client/ResultItem.java
r1621 r1625 1 // ResultItem.java 1 /********************************************************************** 2 * 3 * ResultBox.java -- a list of phrases in the Phind java interface 4 * 5 * Copyright 1997-2000 Gordon W. Paynter 6 * Copyright 2000 The New Zealand Digital Library Project 7 * 8 * A component of the Greenstone digital library software 9 * from the New Zealand Digital Library Project at the 10 * University of Waikato, New Zealand. 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * 26 *********************************************************************/ 2 27 3 /* 28 /********************************************************************* 4 29 5 A result item object holds the data describing a single line 6 returned from a query to the server. It therefore contains 7 either information describing a phrase or a URL. 30 This class is used in the Phind java applet (Phind.java). 8 31 9 The ResultCanvas class maintains an array of ResultItems, 10 a nd contains code to display them when it is appropriate to11 do so.32 A result item object holds the data describing a single line returned from 33 a query to the server. It therefore contains either information describing 34 a phrase or a URL. 12 35 13 */ 36 **********************************************************************/ 37 14 38 15 39 public class ResultItem { 16 40 17 // There are four kinds of item 18 // 1. a phrase 19 // 2. a document (or URL) 20 // 3. a "get more phrases" marker 21 // 4. a "get more documents" marker 22 final static int phraseItem = 1; 23 final static int morePhrases = 2; 24 final static int documentItem = 3; 25 final static int moreDocuments = 4; 41 // There are four kinds of item 42 // 1. a phrase 43 // 2. a document (or URL) 44 // 3. a "get more phrases" marker 45 // 4. a "get more documents" marker 26 46 27 // What kind is this item: 28 int kind; 47 final static int phraseItem = 1; 48 final static int morePhrases = 2; 49 final static int documentItem = 3; 50 final static int moreDocuments = 4; 29 51 30 // The symbol of this item as a string (rule) and integer 31 String rule; 32 int symbol; 52 // What kind is this item: 53 int kind; 33 54 34 // The term frequency of the item 35 int freq; 55 // The symbol of this item as a string (rule) and integer 56 String rule; 57 int symbol; 36 58 37 // The documentfrequency of the item38 int documents;59 // The term frequency of the item 60 int freq; 39 61 40 // Can this item be expanded?41 int expansion;62 // The document frequency of the item 63 int documents; 42 64 43 // The text of the item, split into a prefix, body, and suffix. 44 // For phrases, the body is the search term and the prefix and suffix 45 // the surrounding text in the new phrase. 46 // For URLs the prefix and suffix are ignored. 47 String prefix; 48 String body; 49 String suffix; 65 // Can this item be expanded? ---- obsolete? 66 int expansion; 67 68 // The text of the item, split into a prefix, body, and suffix. 69 // For phrases, the body is the search term and the prefix and suffix 70 // the surrounding text in the new phrase. 71 // For URLs the prefix and suffix are ignored. 72 String prefix; 73 String body; 74 String suffix; 50 75 51 76 52 // Create a ResultItem, 53 // given all the relevant information as String objects. 54 ResultItem(String r, String f, String e, String d, 55 String p, String b, String s) { 77 // Create a ResultItem for a phrase 78 ResultItem(String r, String f, String d, 79 String p, String b, String s) { 56 80 57 rule = r; 58 symbol = Integer.valueOf(rule).intValue(); 59 if (symbol < 10000000) { 60 kind = phraseItem; 61 } else { 62 kind = documentItem; 81 System.out.println("ResultItem (phrase): " + r + " (" + f + ", " + d + ")"); 82 83 kind = phraseItem; 84 rule = r; 85 symbol = Integer.valueOf(rule).intValue(); 86 87 freq = Integer.valueOf(f).intValue(); 88 documents = Integer.valueOf(d).intValue(); 89 expansion = 0; 90 91 prefix = p; 92 body = b; 93 suffix = s; 63 94 } 64 95 65 freq = Integer.valueOf(f).intValue();66 expansion = Integer.valueOf(e).intValue();67 documents = Integer.valueOf(d).intValue();68 96 69 prefix = p; 70 body = b; 71 suffix = s; 72 } 97 // Create a ResultItem for a document 98 ResultItem(String hash, String title, String df) { 99 100 System.out.println("ResultItem (document): " + hash + " (" + df + ")"); 101 102 kind = documentItem; 103 rule = hash; 104 body = title; 105 documents = Integer.valueOf(df).intValue(); 106 107 // not needed for a document 108 symbol = 0; 109 freq = 0; 110 expansion = 0; 111 prefix = ""; 112 suffix = ""; 113 } 73 114 74 115 75 // Create a ResultItem, 76 // given the kind and no other information 77 ResultItem(int k, String r) { 116 // Create an empty ResultItem of a given kind 117 ResultItem(int k, String r) { 78 118 79 119 kind = k; 80 120 81 82 121 rule = r; 122 symbol = -1; 83 123 84 85 86 124 freq = 0; 125 expansion = 0; 126 documents = 0; 87 127 88 89 90 91 }128 prefix = ""; 129 body = ""; 130 suffix = ""; 131 } 92 132 93 // Return the full phrase described by the item.94 public String toString() {95 96 97 98 99 100 }133 // Return the full phrase described by the item. 134 public String toString() { 135 String result = ""; 136 if (!prefix.equals("")) result = prefix.replace(' ', '+') + "+"; 137 result += body.replace(' ', '+'); 138 if (!suffix.equals("")) result += "+" + suffix.replace(' ', '+'); 139 return(result.trim()); 140 } 101 141 102 // Is the item a phrase?103 public boolean isPhrase() {104 105 }142 // Is the item a phrase? 143 public boolean isPhrase() { 144 return (kind == phraseItem); 145 } 106 146 107 // Is the item a document?108 public boolean isDocument() {109 110 }147 // Is the item a document? 148 public boolean isDocument() { 149 return (kind == documentItem); 150 } 111 151 112 public boolean isMorePhrases() {113 114 }152 public boolean isMorePhrases() { 153 return (kind == morePhrases); 154 } 115 155 116 public boolean isMoreDocuments() {117 118 }156 public boolean isMoreDocuments() { 157 return (kind == moreDocuments); 158 } 119 159 120 160
Note:
See TracChangeset
for help on using the changeset viewer.