Changeset 6382
- Timestamp:
- 2004-01-09T14:48:06+13:00 (20 years ago)
- Location:
- trunk/gli/src/org/greenstone/gatherer
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gli/src/org/greenstone/gatherer/gui/AboutDialog.java
r6318 r6382 2 2 *######################################################################### 3 3 * 4 * A component of the Gatherer application, part of the Greenstone digital 5 * library suite from the New Zealand Digital Library Project at the 6 * University of Waikato, New Zealand. 4 * A component of the Greenstone Librarian Interface (GLI) application, 5 * part of the Greenstone digital library software suite from the New 6 * Zealand Digital Library Project at the University of Waikato, 7 * New Zealand. 7 8 * 8 * <BR><BR> 9 * Author: John Thompson 10 * Greenstone Project, New Zealand Digital Library 11 * University of Waikato 12 * http://www.nzdl.org 9 13 * 10 * Author: John Thompson, Greenstone Digital Library, University of Waikato 11 * 12 * <BR><BR> 13 * 14 * Copyright (C) 1999 New Zealand Digital Library Project 15 * 16 * <BR><BR> 14 * Copyright (C) 2004 New Zealand Digital Library, University of Waikato 17 15 * 18 16 * This program is free software; you can redistribute it and/or modify … … 21 19 * (at your option) any later version. 22 20 * 23 * <BR><BR>24 *25 21 * This program is distributed in the hope that it will be useful, 26 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 24 * GNU General Public License for more details. 29 *30 * <BR><BR>31 25 * 32 26 * You should have received a copy of the GNU General Public License … … 45 39 import org.greenstone.gatherer.util.Utility; 46 40 47 /** 48 * @author John Thompson, Greenstone Digital Library, University of Waikato49 * @version 2. 3c41 /** Generates a pretty about dialog which not only thanks those for their contributions but also meets our legal requirements if we wish to ship the JVM with GLI. 42 * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato 43 * @version 2.41 final 50 44 */ 51 52 45 // RICOH SOURCE CODE PUBLIC LICENSE - http://www.risource.org/RPL/RPL-1.0A.shtml 53 46 public class AboutDialog 54 47 extends JDialog { 48 /** The default size of the about dialog. */ 49 static final private Dimension SIZE = new Dimension(600, 325); 50 /** The size of the GLI icon to display on dialog. */ 51 static final private int ICON_SIZE = 65; 52 /** A reference to ourself so that our inner classes can dismiss us. */ 55 53 private AboutDialog self; 54 /** The button used for dismissing the about dialog. */ 56 55 private JButton close_button; 57 58 static final private Dimension SIZE = new Dimension(600, 325); 59 static final private int ICON_SIZE = 65; 60 56 /** The constructor not only builds, but displays the about dialog. This method doesn't return until the dialog is dismissed. 57 * @param parent the JFrame which owns this dialog for use in centering the dialog 58 * @see org.greenstone.gatherer.Dictionary#get 59 * @see org.greenstone.gatherer.Dictionary#setBoth 60 * @see org.greenstone.gatherer.Dictionary#setText 61 * @see org.greenstone.gatherer.gui.AboutDialog.CloseButtonListener 62 * @see org.greenstone.gatherer.gui.GLIButton 63 * @see org.greenstone.gatherer.util.Utility#getImage 64 * @see org.greenstone.gatherer.util.Utility#PROGRAM_NAME 65 * @see org.greenstone.gatherer.util.Utility#PROGRAM_VERSION 66 */ 61 67 public AboutDialog(JFrame parent) { 62 68 super(parent, Dictionary.get("AboutDialog.Title"), true); … … 154 160 show(); 155 161 } 156 162 /** Listens for actions upon the close button, and when detected closes the dialog. */ 157 163 private class CloseButtonListener 158 164 implements ActionListener { 165 /** Called whenever an action occurs on the close button, thus asking the dialog to close. 166 * @param event an ActionEvent containing information about the button press 167 */ 159 168 public void actionPerformed(ActionEvent event) { 160 169 self.hide(); -
trunk/gli/src/org/greenstone/gatherer/util/AppendLineOnlyFileDocument.java
r6318 r6382 1 /** 2 *######################################################################### 3 * 4 * A component of the Greenstone Librarian Interface (GLI) application, 5 * part of the Greenstone digital library software suite from the New 6 * Zealand Digital Library Project at the University of Waikato, 7 * New Zealand. 8 * 9 * Author: John Thompson, Greenstone Project, New Zealand Digital Library, 10 * University of Waikato 11 * http://www.nzdl.org 12 * 13 * Copyright (C) 2004 New Zealand Digital Library, University of Waikato 14 * 15 * This program is free software; you can redistribute it and/or modify 16 * it under the terms of the GNU General Public License as published by 17 * the Free Software Foundation; either version 2 of the License, or 18 * (at your option) any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 * 25 * You should have received a copy of the GNU General Public License 26 * along with this program; if not, write to the Free Software 27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 28 *######################################################################## 29 */ 30 1 31 package org.greenstone.gatherer.util; 2 32 … … 12 42 import org.greenstone.gatherer.util.StaticStrings; 13 43 14 /** A Document whose underlying data is stored in a RandomAccessFile, and whose Element implementations lack the memory hogging problems associated with anything that extends the AbstractDocument class. This Document, for reasons of time constraints and sanity, only provides an editting ability of appending new lines to the end of the current document, perfect for our logging needs, completely useless for text editing purposes. Furthermore, since the append actions tend to somewhat swamp the IO, I'll temporarily store strings in the structure model, and write them out using a separate thread. */ 44 /** A Document whose underlying data is stored in a RandomAccessFile, and whose Element implementations lack the memory hogging problems associated with anything that extends the AbstractDocument class. This Document, for reasons of time constraints and sanity, only provides an editting ability of appending new lines to the end of the current document, perfect for our logging needs, completely useless for text editing purposes. Furthermore, since the append actions tend to somewhat swamp the IO, I'll temporarily store strings in the structure model, and write them out using a separate thread. 45 * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato 46 * @version 2.41 final 47 */ 15 48 public class AppendLineOnlyFileDocument 16 49 implements Document { 17 18 static final private String EMPTY_STR = ""; 50 /** A default string to append at the start of each log file. Of special note is the beginning X character that will, upon completion of the import/build process, be replaced with a letter indicating the final status of this build attempt. */ 19 51 static final private String GLI_HEADER_STR = "X:GLI Import and Build log:"; 20 52 /** The root element of the document model. */ 21 53 private AppendLineOnlyFileDocumentElement root_element; 54 /** The current owner of this document, useful for callbacks when certain tasks are complete. */ 22 55 private AppendLineOnlyFileDocumentOwner owner; 56 /** A list of listeners attached to this document. */ 23 57 private EventListenerList listeners_list; 24 private HashMap cache;58 /** This properties hash map allows you to store any metadata about this document for later review. */ 25 59 private HashMap properties; 60 /** Indicates the current length of the underlying file (which may not equal the current number of characters in the document). */ 26 61 private long length; 62 /** The random access file which will back this document model. */ 27 63 private RandomAccessFile file; 64 /** The filename given to the underlying file. */ 65 private String filename; 66 /** An independant thread responsible for writing the 'in memory' contents of the document model to the random access file as appropriate. This is done so IO lag does not effect the gui as much as it used to. */ 28 67 private WriterThread writer; 29 68 /** The constructor is responsible for creating several necessary data structures as well as opening the random access file. When it creates the new file, as it is wont to do, it will immediately add the special header line defined above. 69 * @param filename the absolute path name of the file as a String 70 * @see org.greenstone.gatherer.Gatherer#println 71 * @see org.greenstone.gatherer.Gatherer#printStackTrace 72 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement 73 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread 74 * @see org.greenstone.gatherer.util.StaticStrings#NEW_LINE_CHAR 75 */ 30 76 public AppendLineOnlyFileDocument(String filename) { 31 ///ystem.err.println("Creating log: " + filename);32 // Initialization 33 this. cache = new HashMap();77 Gatherer.println("Creating log: " + filename); 78 // Initialization 79 this.filename = filename; 34 80 this.listeners_list = new EventListenerList(); 35 81 this.properties = new HashMap(); … … 65 111 } 66 112 67 /** Adds a document listener for notification of any changes. */ 113 /** Adds a document listener for notification of any changes. 114 * @param listener the new DocumentListener to keep track of 115 */ 68 116 public void addDocumentListener(DocumentListener listener) { 69 117 ///ystem.err.println("addDocumentListener(" + listener + ")"); … … 71 119 } 72 120 73 /** Append some content after the document. */ 121 /** Append some content after the document. 122 * @param str the String to add as a new line in the document 123 * @see org.greenstone.gatherer.Gatherer#printStackTrace 124 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement 125 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentEvent 126 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#queue 127 */ 74 128 public void appendLine(String str) { 75 129 // Ensure the string ends in a newline … … 105 159 } 106 160 107 /** Returns a position that will track change as the document is altered. */ 161 /** Returns a position that will track change as the document is altered. 162 * @param offs the position offset as an int 163 * @return the Position to be monitored 164 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentPosition 165 */ 108 166 public Position createPosition(int offs) { 109 167 return new AppendLineOnlyFileDocumentPosition(offs); 110 168 } 111 169 112 /** Gets the default root element for the document model. */ 170 /** The destructor is implemented to ensure the current log file has finished transferring from memory to disk, and that the random access file is properly closed, before GLI exits. 171 * @see org.greenstone.gatherer.Gatherer#println 172 * @see org.greenstone.gatherer.Gatherer#printStackTrace 173 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#finish 174 */ 175 public void destroy() { 176 try { 177 writer.finish(); 178 System.err.println("Closing document."); 179 file.close(); 180 } 181 catch(Exception exception) { 182 Gatherer.println("Exception in AppendLineOnlyFileDocument.destroy() - unexpected"); 183 Gatherer.printStackTrace(exception); 184 } 185 } 186 187 /** Gets the default root element for the document model. 188 * @return the root Element of this document 189 */ 113 190 public Element getDefaultRootElement() { 114 191 return root_element; 115 192 } 116 193 117 /** Returns the length of the data. */ 194 /** Returns the length of the data. 195 * @return the length as an int (not a long) 196 */ 118 197 public int getLength() { 119 198 return (int) length; 120 199 } 121 200 122 /** A version of get length which essentiallyreturns the offset to the start of the last line in the document.201 /** A version of get length which returns the offset to the start of the last line in the document. 123 202 * @return the offset length as an int 203 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement 124 204 */ 125 205 public int getLengthToNearestLine() { … … 133 213 } 134 214 215 /** Retrieve a property that has previously been set for this document. 216 * @param key the key String under which the vaue is stored 217 * @return the value which is also a String, or null if no such value 218 */ 135 219 public Object getProperty(Object key) { 136 220 return properties.get(key); 137 221 } 138 222 223 /** Determine if the writer thread is still running, ie a log file which is currently open for writing 224 * @return true if the writer is still active, false otherwise 225 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#isStillWriting 226 */ 139 227 public boolean isStillWriting() { 140 228 return writer.isStillWriting(); 141 229 } 142 230 143 /** Gets a sequence of text from the document. */ 231 /** Gets a sequence of text from the document. 232 * @param offset the starting offset for the fragment of text required, as an int 233 * @param l the length of the text, also as an int 234 * @see org.greenstone.gatherer.Gatherer#printStackTrace 235 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement 236 * @see org.greenstone.gatherer.util.StaticStrings#EMPTY_STR 237 */ 144 238 public String getText(int offset, int l) 145 239 throws BadLocationException { 146 240 String request = "getText(" + offset + ", " + l + ")"; 147 241 ///ystem.err.println(request); 148 String text = null; //(String) cache.get(request);242 String text = null; 149 243 if(text == null || text.length() < l) { 150 244 try { … … 152 246 ///ystem.err.println("file_length = " + file_length + ", length = " + length); 153 247 if(l == 0) { 154 text = EMPTY_STR;248 text = StaticStrings.EMPTY_STR; 155 249 } 156 250 else if(0 <= offset && offset < length && (offset + l) <= length) { … … 183 277 throw new BadLocationException("AppendLineOnlyDocument.getText(" + offset + ", " + l + ")", offset); 184 278 } 185 //cache.put(request, text);186 279 } 187 280 request = null; … … 189 282 } 190 283 191 /** Fetches the text contained within the given portion of the document. */ 284 /** Fetches the text contained within the given portion of the document. 285 * @param offset the starting offset of the desired text fragment, as an int 286 * @param length the length of the text also as an int 287 * @param txt the Segment into which the text fragment should be placed 288 */ 192 289 public void getText(int offset, int length, Segment txt) 193 290 throws javax.swing.text.BadLocationException { … … 199 296 } 200 297 298 /** Set a property for this document. 299 * @param key the key to store the value under, as a String 300 * @param value the property value itself also as a String 301 */ 201 302 public void putProperty(Object key, Object value) { 202 303 properties.put(key, value); 203 304 } 204 305 306 /** Determine if this document is ready by testing if it has an open descriptor to the random access file. 307 * @return true if the file exists thus the document is ready, false otherwise 308 */ 205 309 public boolean ready() { 206 310 return (file != null); 207 311 } 208 312 209 //Removes a document listener. 313 /** Removes a document listener. 314 * @param listener the Document we wish to remove 315 */ 210 316 public void removeDocumentListener(DocumentListener listener) { 211 ///ystem.err.println("removeDocumentListener()");212 317 listeners_list.remove(DocumentListener.class, listener); 213 318 } 214 319 320 /** Whenever the user requests a change of the loaded log, this method is called to ensure the previous log has been completely written to file. Note that this only garuentees that text fragments currently queued for writing will be correctly written - while the behaviour is undefined for text fragments added after this call (some may write depending on several race conditions). 321 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#exit 322 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#finish 323 */ 215 324 public void setExit() { 216 325 writer.exit(); 217 } 218 326 writer.finish(); 327 } 328 329 /** Establish the current owner of this document. 330 * @param owner the current AppendLineOnlyFileDocumentOwner 331 */ 219 332 public void setOwner(AppendLineOnlyFileDocumentOwner owner) { 220 333 this.owner = owner; 221 334 } 222 335 223 /** To record the final state of the logging process we reserve a single character at the start of the file. */ 336 /** To record the final state of the logging process we reserve a single character at the start of the file, and then replace it when the build process is complete. 337 * @param character the final status char to replace the X at the start of the log 338 * @see org.greenstone.gatherer.Gatherer#printStackTrace 339 */ 224 340 public synchronized void setSpecialCharacter(char character) { 225 341 try { … … 232 348 } 233 349 350 /** Request a text representation of this document which currently returns the filename. 351 * @return the text as a String 352 */ 353 public String toString() { 354 return filename; 355 } 356 357 /** This method reads a fragment of text from the underlying random access file. It is synchronized so that the file isn't being written to at the same time. 358 * @param start_offset the offset within the file to set the read pointer at, as a long 359 * @param l the number of characters to read as an int 360 */ 234 361 private synchronized String read(long start_offset, int l) 235 362 throws IOException { … … 242 369 } 243 370 371 /** This methods writes a fragment of text to the underlying random access file. It is synchronized so that the file isn't being read from at the same time. 372 * @param start_offset the offset within the file to set the write pointer at, as a long 373 * @param end_offset the final offset of the new text fragment within the file, as a long. This is used to extend the file to be the correct length 374 * @param str the String to be written 375 * @param l the number of characters from str to be written, as an int 376 */ 244 377 private synchronized void write(long start_offset, long end_offset, String str, int l) 245 378 throws IOException { … … 251 384 } 252 385 386 /** This class provides the building-block for the document model. Each element is a line in the document, or has no content but contains several child elements. Due to the basic nature of what we are modelling only the root node has children. */ 253 387 private class AppendLineOnlyFileDocumentElement 254 388 extends ArrayList 255 389 implements Element { 256 390 /** Our parent Element. */ 257 391 private Element parent; 392 /** The offset to the end of our fragment(s) of text, in respect to the entire document. */ 258 393 private long end; 394 /** The offset to the start of our fragment(s) of text, in respect to the entire document. */ 259 395 private long start; 396 /** If we haven't been written to file yet, this contains the text fragment itself. */ 260 397 private String content; 261 262 /** Construct a new root element, which can have no content, but calculates its start and end from its children. 263 * @param start the starting offset as a long 264 * @param end the ending offset as a long. 265 */ 398 399 /** Construct a new root element, which can have no content, but calculates its start and end from its children. */ 266 400 public AppendLineOnlyFileDocumentElement() { 267 401 super(); … … 271 405 } 272 406 273 274 407 /** Construct a new element, whose content is found in bytes start to end - 1 within the random access file backing this document. 275 * @param 276 * @param end the ending offset as a long.408 * @param start the starting offset as a long 409 * @param end the ending offset as a long 277 410 */ 278 411 public AppendLineOnlyFileDocumentElement(long start, long end) { … … 284 417 285 418 /** Construct a new element, whose content is provided, but should at some later time be written to bytes start to end - 1 in the random access file backing this document. 286 * @param start the starting offset as a long 287 * @param end the ending offset as a long. 419 * @param start the starting offset as a long 420 * @param end the ending offset as a long 421 * @param content the text fragment String which we represent in the model 288 422 */ 289 423 public AppendLineOnlyFileDocumentElement(long start, long end, String content) { … … 295 429 } 296 430 431 /** Add the given node as one of our children. 432 * @param child the new child Element 433 */ 297 434 public void add(Element child) { 298 435 super.add(child); … … 300 437 } 301 438 439 /** Having written the content to file this method removes it from the element. */ 302 440 public void clearContent() { 303 441 content = null; 304 442 } 305 443 306 /** This document does not allow content markup. */ 444 /** This document does not allow content markup. 445 * @return always returns null 446 */ 307 447 public AttributeSet getAttributes() { 308 448 return null; 309 449 } 310 450 451 /** Retrieve the current content of this element, which may be the text fragment this element represents. 452 * @return either the text fragment as a String, or null if the fragment has already been written to disk 453 */ 311 454 public String getContent() { 312 455 return content; … … 315 458 /** Fetches the document associated with this element. 316 459 * @return the AppendLineOnlyDocument containing this element 460 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument 317 461 */ 318 462 public Document getDocument() { … … 320 464 } 321 465 322 /** Fetches the child element at the given index. */ 466 /** Fetches the child element at the given index. 467 * @param index the int index of the element to retrieve 468 * @return the requested Element 469 */ 323 470 public Element getElement(int index) { 324 471 Element element; … … 332 479 } 333 480 334 /** Gets the number of child elements contained by this element. */ 481 /** Gets the number of child elements contained by this element. 482 * @return an int 483 */ 335 484 public int getElementCount() { 336 485 return size(); 337 486 } 338 487 339 /** Gets the child element index closest to the given offset. */ 488 /** Gets the child element index closest to the given offset. 489 * @param offset the offset within the text of the document, which due to the way the model is built must fll within the bounds of one of our child nodes 490 * @return the closest index as an int 491 */ 340 492 public int getElementIndex(int offset) { 341 493 int index = -1; … … 362 514 } 363 515 364 /** Fetches the offset from the beginning of the document that this element ends at. */ 516 /** Fetches the offset from the beginning of the document that this element ends at. 517 * @return the offset as an int 518 */ 365 519 public int getEndOffset() { 366 520 if(parent != null) { … … 375 529 /** This method retrieves the name of the element, however names are not important in this document so the name is always an empty string. 376 530 * @return an empty String 531 * @see org.greenstone.gatherer.util.StaticStrings#EMPTY_STR 377 532 */ 378 533 public String getName() { … … 380 535 } 381 536 382 /** Fetches the parent element. */ 537 /** Fetches the parent element. 538 * @return the parent Element 539 */ 383 540 public Element getParentElement() { 384 541 return parent; 385 542 } 386 543 387 /** Fetches the offset from the beginning of the document that this element begins at. */ 544 /** Fetches the offset from the beginning of the document that this element begins at. 545 * @return the offset as an int 546 */ 388 547 public int getStartOffset() { 389 548 if(parent != null) { … … 395 554 } 396 555 397 /** Since this is a very simple model, only the root node can have children. All the children are leaves. */ 556 /** Since this is a very simple model, only the root node can have children. All the children are leaves. 557 * @return true if this is the root node, false otherwise 558 */ 398 559 public boolean isLeaf() { 399 560 return (parent != null); 400 561 } 401 562 563 /** Establish the parent of this element 564 * @param parent the parent Element 565 */ 402 566 public void setParent(Element parent) { 403 567 this.parent = parent; 404 568 } 405 569 } 406 570 // AppendLineOnlyFileDocumentElement 571 572 /** This event is created to encapsulate the details of some change to the document. */ 407 573 private class AppendLineOnlyFileDocumentEvent 408 574 implements DocumentEvent { 409 575 /** The type of change event. */ 410 576 private DocumentEvent.EventType type; 577 /** The element this change occured to, or in. */ 411 578 private AppendLineOnlyFileDocumentElement element; 579 /** Another encapsulating class which contains further detail about the change itself. */ 412 580 private AppendLineOnlyFileDocumentElementChange element_change; 581 /** The length of the text fragment affected by the change. */ 413 582 private int len; 583 /** The offset within the document of the start of the change. */ 414 584 private int offset; 415 585 586 /** Construct a new AppendLineOnlyFileDocumentEvent given the pertinant details. 587 * @param element the AppendLineOnlyFileDocumentElement affected by this change 588 * @param offset the offset within the document of the start of the change 589 * @param len the length of the text fragment affected by the change 590 * @param type the type of change event 591 */ 416 592 public AppendLineOnlyFileDocumentEvent(AppendLineOnlyFileDocumentElement element, int offset, int len, DocumentEvent.EventType type) { 417 593 this.element = element; … … 422 598 } 423 599 600 /** Retrieve the docment which generated this event. 601 * @return the Document 602 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument 603 */ 424 604 public Document getDocument() { 425 605 return AppendLineOnlyFileDocument.this; 426 606 } 427 607 608 /** Retrieve the length of the change. 609 * @return the length as an int 610 */ 428 611 public int getLength() { 429 612 return len; 430 613 } 431 614 615 /** Retrieve the start offset of the change. 616 * @return the offset as an int 617 */ 432 618 public int getOffset() { 433 619 return offset; 434 620 } 435 621 622 /** Retrieve the type of change. 623 * @return the type as a DocumentEvent.EventType 624 */ 436 625 public DocumentEvent.EventType getType() { 437 626 return type; 438 627 } 439 628 440 // ***** IGNORE ***** 629 /** Retrieve the element change object which further describes the changes. Of course given that we only allow the appending of new lines there really is only one type of event. 630 * @param elem implementation side-effect 631 * @return a DocumentEvent.ElementChange 632 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentEvent.AppendLineOnlyFileDocumentElementChange 633 */ 441 634 public DocumentEvent.ElementChange getChange(Element elem) { 442 635 if(element_change == null) { … … 446 639 } 447 640 641 /** A pretty unexciting implementation of the document element change class. This usually describes the myriad of possible change events that can occur on a document. However we only allow line appends so there is really only one type of change. */ 448 642 private class AppendLineOnlyFileDocumentElementChange 449 643 implements DocumentEvent.ElementChange { 450 644 /** This array always contains the one Element that was appended. */ 451 645 private Element[] children_added; 646 /** This Element array is always empty. */ 452 647 private Element[] children_removed; 648 /** The index of the affected element within its parents children. */ 453 649 private int index; 650 /** Construct a new AppendLineOnlyFileDocumentElementChange with the default 'append line' details. */ 454 651 public AppendLineOnlyFileDocumentElementChange() { 455 652 children_added = new Element[1]; … … 458 655 index = root_element.indexOf(element); 459 656 } 460 /** Gets the child element that was added to the given parent element. 657 658 /** Gets the child element that was appended to the parent element. 461 659 * @return an Element[] containing the added element 462 660 */ … … 464 662 return children_added; 465 663 } 664 466 665 /** This model does not allow elements to be removed. 467 666 * @return an Element[] containing nothing … … 485 684 } 486 685 } 487 } 488 686 // AppendLineOnlyFileDocumentElementChange 687 } 688 // AppendLineOnlyFileDocumentEvent 689 690 /** This class denoted a position within our document by an offset. Quite possibly the last interesting class I've ever had to deal with, but you have to implement it so here goes... */ 489 691 private class AppendLineOnlyFileDocumentPosition 490 692 implements Position { 491 693 /** The offset within our document. */ 492 694 private int offset; 493 695 /** Construct a new position given an offset. 696 * @param offset the offset as an int 697 */ 494 698 public AppendLineOnlyFileDocumentPosition(int offset) { 495 699 this.offset = offset; 496 700 } 497 701 /** Retrieve the offset of this position. 702 * @return the offset as an int 703 */ 498 704 public int getOffset() { 499 705 return offset; 500 706 } 501 707 } 502 708 // AppendLineOnlyFileDocumentPosition 709 710 /** This thread is responsible to writing the in memory text fragment contents of the document elements out to the random access file. The writing proceedure is implemented this way so that the gui doesn't take the performance hit of the IO. */ 503 711 private class WriterThread 504 712 extends Thread { 505 713 /** When true was are being told to assume the contents of the queue are now static, and once completed the queue will be empty (and not expecting any new jobs). Used to finish the queue before the GLI exits. */ 714 private boolean empty_queue; 715 /** Setting this flag to true tells the writer to stop regardless of whether there are items left on the queue. */ 506 716 private boolean exit; 717 /** When the writer thread is busy writing content to the file this flag is set to true. */ 507 718 private boolean running; 719 /** When the writer thread is running, but has emptied the current queue and so is waiting, this flag is set to true. */ 720 private boolean waiting; 721 /** The fragment queue as a Vector (for thread reasons). */ 508 722 private Vector queue; 509 723 /** Construct a new writer thread with an initially empty queue. */ 510 724 public WriterThread() { 511 725 super("WriterThread"); 726 empty_queue = false; 512 727 exit = false; 513 728 queue = new Vector(); 514 } 515 729 waiting = false; 730 } 731 732 /** This method is called to ask the writer thread to die after it finishes any current write proceceedure. */ 516 733 public synchronized void exit() { 517 734 //print("WriterThread.exit() start"); … … 521 738 } 522 739 740 /** When this returns there are no jobs waiting in the queue. */ 741 public void finish() { 742 if(!queue.isEmpty() && running) { 743 ///ystem.err.println("Somethings gone wrong, as there are still " + queue.size() + " items to be written out and yet the thread seems to be waiting."); 744 empty_queue = true; 745 run(); 746 } 747 } 748 749 /** Determine if the writer is currently running. 750 * @return true if it is, false if it has been exited or if it was never running in the first place (an old log) 751 */ 523 752 public boolean isStillWriting() { 524 753 return running; 525 754 } 526 755 756 /** The run method of this thread checks if there are any document elements queued to be written to file, and then writes them as necessary. 757 * @see org.greenstone.gatherer.Gatherer#printStackTrace 758 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument 759 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement 760 */ 527 761 public void run() { 762 exit = false; 528 763 running = true; 529 764 while(!exit) { … … 542 777 } 543 778 } 779 else if(empty_queue) { 780 exit = true; 781 } 544 782 else { 545 783 synchronized(this) { 546 784 try { 547 //print("WriterThread.wait() start"); 785 print("WriterThread.wait() start"); 786 waiting = true; 548 787 wait(); 549 //print("WriterThread.wait() complete");550 788 } 551 catch(Exception e rror) {789 catch(Exception exception) { 552 790 } 791 print("WriterThread.wait() complete"); 792 waiting = false; 553 793 } 554 794 } 555 795 } 796 print("WriterThread completely finished. Exiting."); 556 797 running = false; 557 798 if(owner != null) { … … 560 801 } 561 802 803 /** Enqueue a document element to have its text content written to file. 804 * @param element the Element needing its content written out 805 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement#getContent 806 */ 562 807 public synchronized void queue(Element element) { 563 //print("WriterThread.queue() start");808 print("WriterThread.queue(): " + ((AppendLineOnlyFileDocumentElement)element).getContent()); 564 809 queue.add(element); 565 810 notify(); 566 //print("WriterThread.queue() complete");567 568 }811 } 812 } 813 // WriterThread 569 814 570 815 // ***** METHODS WE ARE NOW IGNORING BECAUSE WE ARE VIRTUALLY READ-ONLY ***** 571 816 572 /** Adds an undo listener for notification of any changes. */ 817 /** Not implemented. Add a new undo listener to this document. 818 * @param listener UndoableEditListener 819 */ 573 820 public void addUndoableEditListener(UndoableEditListener listener) {} 574 821 575 /** */ 576 public Position getEndPosition() { 577 ///ystem.err.println("getEndPosition()"); 578 return null; 579 } 580 581 /** Gets all root elements defined. */ 582 public Element[] getRootElements() {return null;} 822 /** Not implemented. Get the last position in the document. 823 * @return null 824 */ 825 public Position getEndPosition() { return null; } 826 827 /** Not implemented. Gets all root elements defined. 828 * @return null 829 */ 830 public Element[] getRootElements() { return null; } 583 831 584 public Position getStartPosition() {585 ///ystem.err.println("getStartPosition()"); 586 return null; 587 }832 /** Not implemented. Retrieve the first position in the document. 833 * @return null 834 */ 835 public Position getStartPosition() { return null; } 588 836 837 /** Not implemented. Insert a text fragment into our document. 838 * @param offset int 839 * @param str String 840 * @param a AttributeSet 841 */ 589 842 public void insertString(int offset, String str, AttributeSet a) {} 590 843 591 /** Removes some content from the document. */ 844 /** Not implemented. Removes some content from the document. 845 * @param offs int 846 * @param len int 847 */ 592 848 public void remove(int offs, int len) {} 593 849 594 /** Removes an undo listener. */ 850 /** Not implemented. Removes an undo listener. 851 * @param listener UndoableEditListener 852 */ 595 853 public void removeUndoableEditListener(UndoableEditListener listener) {} 596 854 597 /** Renders a runnable apparently. */ 855 /** Not implemented. Renders a runnable apparently - whatever that means. 856 * @param r Runnable 857 */ 598 858 public void render(Runnable r) {} 599 859 860 // DEBUG ONLY 861 862 /** Print a message to the GLI debug file stream. 863 * @param message the message to be written as a String 864 * @see org.greenstone.gatherer.Gatherer#println 865 */ 600 866 static synchronized public void print(String message) { 601 867 Gatherer.println(message); 602 868 } 603 869 870 /** Create a test document with the ability to add new lines of text as necessary. 871 * @param args the initial starting arguments as a String array 872 * @see org.greenstone.gatherer.gui.GLIButton 873 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument 874 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.ReadButtonListener 875 */ 604 876 static public void main(String[] args) { 605 877 JFrame frame = new JFrame("AppendLineOnlyFileDocument Test"); … … 616 888 JButton read_button = new GLIButton("Read Huge File"); 617 889 read_button.setMnemonic(KeyEvent.VK_R); 618 read_button.addActionListener(new ActionListener() { 619 public void actionPerformed(ActionEvent event) { 620 Thread task = new Thread("LoadHugeFileThread") { 621 public void run() { 622 // Load the specified document 623 try { 624 BufferedReader in = new BufferedReader(new FileReader(new File("big.txt"))); 625 String line; 626 627 while ((line = in.readLine()) != null) { 628 document.appendLine(line); 629 try { 630 // Wait a random ammount of time. 631 synchronized(this) { 632 //print("LoadHugeFileThread.wait() start"); 633 wait(100); 634 //print("LoadHugeFileThread.wait() complete"); 635 } 636 } 637 catch(Exception error) { 638 error.printStackTrace(); 639 } 640 } 641 642 } catch (Exception error) { 643 error.printStackTrace(); 644 } 645 } 646 }; 647 task.start(); 648 649 } 650 }); 890 read_button.addActionListener(new ReadButtonListener(document)); 651 891 content.setLayout(new BorderLayout()); 652 892 content.add(new JScrollPane(text_area), BorderLayout.CENTER); … … 655 895 frame.show(); 656 896 } 897 898 /** Listens for actions on the read button, and if detected creates a new ReadTask to test the document. */ 899 static private class ReadButtonListener 900 implements ActionListener { 901 /** The AppendLineOnlyFileDocument object we are testing. */ 902 private AppendLineOnlyFileDocument document; 903 904 /** All the constructor does is take a copy of the document to test. 905 * @param document the Document 906 */ 907 public ReadButtonListener(AppendLineOnlyFileDocument document) { 908 this.document = document; 909 } 910 911 /** When the button is clicked this method is called to create the new task and run it. 912 * @param event an ActionEvent containing further information about the button click 913 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.ReadTask 914 */ 915 public void actionPerformed(ActionEvent event) { 916 Thread task = new ReadTask(document); 917 task.start(); 918 } 919 } 920 921 /** This threaded task opens a large document, aptly named 'big.txt', and then bombards the document object we are testing with lines from the file. This file should be several megs (such as Alice or TREC) to fully test functionality, thread conditions etc. */ 922 static private class ReadTask 923 extends Thread { 924 /** The AppendLineOnlyFileDocument object we are testing. */ 925 private AppendLineOnlyFileDocument document; 926 927 /** Construct a new task which will perform testing on the given document. 928 * @param document the AppendLineOnlyFileDocument to append lines to 929 */ 930 public ReadTask(AppendLineOnlyFileDocument document) { 931 super("LoadHugeFileThread"); 932 this.document = document; 933 } 934 935 /** The runable part of this class opens the file, then reads it in a line at a time, appending these lines to the ever growing document. */ 936 public void run() { 937 // Load the specified document 938 try { 939 BufferedReader in = new BufferedReader(new FileReader(new File("big.txt"))); 940 String line; 941 942 while ((line = in.readLine()) != null) { 943 document.appendLine(line); 944 try { 945 // Wait a random ammount of time. 946 synchronized(this) { 947 //print("LoadHugeFileThread.wait() start"); 948 wait(100); 949 //print("LoadHugeFileThread.wait() complete"); 950 } 951 } 952 catch(Exception error) { 953 error.printStackTrace(); 954 } 955 } 956 957 } catch (Exception error) { 958 error.printStackTrace(); 959 } 960 } 961 } 962 // ReadTask 657 963 } -
trunk/gli/src/org/greenstone/gatherer/util/AppendLineOnlyFileDocumentOwner.java
r5169 r6382 1 /** 2 *######################################################################### 3 * 4 * A component of the Greenstone Librarian Interface (GLI) application, 5 * part of the Greenstone digital library software suite from the New 6 * Zealand Digital Library Project at the University of Waikato, 7 * New Zealand. 8 * 9 * Author: John Thompson 10 * Greenstone Project, New Zealand Digital Library 11 * University of Waikato 12 * http://www.nzdl.org 13 * 14 * Copyright (C) 2004 New Zealand Digital Library, University of Waikato 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License as published by 18 * the Free Software Foundation; either version 2 of the License, or 19 * (at your option) any later version. 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 29 *######################################################################## 30 */ 1 31 package org.greenstone.gatherer.util; 2 32 3 33 import org.greenstone.gatherer.util.AppendLineOnlyFileDocument; 4 34 /** Any class that wants to act as the owner of an AppendLineOnlyFileDocument has to implement this. 35 * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato 36 * @version 2.41 final 37 */ 5 38 public interface AppendLineOnlyFileDocumentOwner { 39 /** Remove the given document from the owner. The is called by the document itself when it no longer needs a hanging reference in the owner class. 40 * @param document the AppendLineOnlyFileDocument to remove 41 */ 6 42 public void remove(AppendLineOnlyFileDocument document); 7 43 } 44 45 46
Note:
See TracChangeset
for help on using the changeset viewer.