Changeset 6382


Ignore:
Timestamp:
2004-01-09T14:48:06+13:00 (20 years ago)
Author:
jmt12
Message:

Finished commenting to 2.41 final standard

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  
    22 *#########################################################################
    33 *
    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.
    78 *
    8  * <BR><BR>
     9 * Author: John Thompson
     10 *         Greenstone Project, New Zealand Digital Library
     11 *         University of Waikato
     12 *         http://www.nzdl.org
    913 *
    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
    1715 *
    1816 * This program is free software; you can redistribute it and/or modify
     
    2119 * (at your option) any later version.
    2220 *
    23  * <BR><BR>
    24  *
    2521 * This program is distributed in the hope that it will be useful,
    2622 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2723 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2824 * GNU General Public License for more details.
    29  *
    30  * <BR><BR>
    3125 *
    3226 * You should have received a copy of the GNU General Public License
     
    4539import org.greenstone.gatherer.util.Utility;
    4640
    47 /**
    48  * @author John Thompson, Greenstone Digital Library, University of Waikato
    49  * @version 2.3c
     41/** 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
    5044 */
    51 
    5245// RICOH SOURCE CODE PUBLIC LICENSE - http://www.risource.org/RPL/RPL-1.0A.shtml
    5346public class AboutDialog
    5447    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. */
    5553    private AboutDialog self;
     54    /** The button used for dismissing the about dialog. */
    5655    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     */
    6167    public AboutDialog(JFrame parent) {
    6268    super(parent, Dictionary.get("AboutDialog.Title"), true);
     
    154160    show();
    155161    }
    156 
     162    /** Listens for actions upon the close button, and when detected closes the dialog. */
    157163    private class CloseButtonListener
    158164    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     */
    159168    public void actionPerformed(ActionEvent event) {
    160169        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
    131package org.greenstone.gatherer.util;
    232
     
    1242import org.greenstone.gatherer.util.StaticStrings;
    1343
    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 */
    1548public class AppendLineOnlyFileDocument
    1649    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. */
    1951    static final private String GLI_HEADER_STR = "X:GLI Import and Build log:";
    20 
     52    /** The root element of the document model. */
    2153    private AppendLineOnlyFileDocumentElement root_element;
     54    /** The current owner of this document, useful for callbacks when certain tasks are complete. */
    2255    private AppendLineOnlyFileDocumentOwner owner;
     56    /** A list of listeners attached to this document. */
    2357    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. */
    2559    private HashMap properties;
     60    /** Indicates the current length of the underlying file (which may not equal the current number of characters in the document). */
    2661    private long length;
     62    /** The random access file which will back this document model. */
    2763    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. */
    2867    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     */
    3076    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;
    3480    this.listeners_list = new EventListenerList();
    3581    this.properties = new HashMap();
     
    65111    }
    66112   
    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     */
    68116    public void addDocumentListener(DocumentListener listener) {
    69117    ///ystem.err.println("addDocumentListener(" + listener + ")");
     
    71119    }
    72120
    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     */
    74128    public void appendLine(String str) {
    75129    // Ensure the string ends in a newline
     
    105159    }
    106160
    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     */
    108166    public Position createPosition(int offs)  {
    109167    return new AppendLineOnlyFileDocumentPosition(offs);
    110168    }
    111169
    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     */
    113190    public Element getDefaultRootElement() {
    114191    return root_element;
    115192    }
    116193
    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     */
    118197    public int getLength() {
    119198    return (int) length;
    120199    }
    121200
    122     /** A version of get length which essentially returns 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.
    123202     * @return the offset length as an int
     203     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement
    124204     */
    125205    public int getLengthToNearestLine() {
     
    133213    }
    134214   
     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     */
    135219    public Object getProperty(Object key) {
    136220    return properties.get(key);
    137221    }
    138222
     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     */
    139227    public boolean isStillWriting() {
    140228    return writer.isStillWriting();
    141229    }
    142230
    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     */
    144238    public String getText(int offset, int l)
    145239    throws BadLocationException {
    146240    String request = "getText(" + offset + ", " + l + ")";
    147241    ///ystem.err.println(request);
    148     String text = null;//(String) cache.get(request);
     242    String text = null;
    149243    if(text == null || text.length() < l) {
    150244        try {
     
    152246        ///ystem.err.println("file_length = " + file_length + ", length = " + length);
    153247        if(l == 0) {
    154             text = EMPTY_STR;
     248            text = StaticStrings.EMPTY_STR;
    155249        }
    156250        else if(0 <= offset && offset < length && (offset + l) <= length) {
     
    183277        throw new BadLocationException("AppendLineOnlyDocument.getText(" + offset + ", " + l + ")", offset);
    184278        }
    185         //cache.put(request, text);
    186279    }
    187280    request = null;
     
    189282    }
    190283
    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     */
    192289    public void getText(int offset, int length, Segment txt)
    193290    throws javax.swing.text.BadLocationException  {
     
    199296    }
    200297   
     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     */
    201302    public void putProperty(Object key, Object value) {
    202303    properties.put(key, value);
    203304    }
    204305
     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     */
    205309    public boolean ready() {
    206310    return (file != null);
    207311    }
    208312   
    209     //Removes a document listener.
     313    /** Removes a document listener.
     314     * @param listener the Document we wish to remove
     315     */
    210316    public void removeDocumentListener(DocumentListener listener) {
    211     ///ystem.err.println("removeDocumentListener()");
    212317    listeners_list.remove(DocumentListener.class, listener);
    213318    }
    214319
     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     */
    215324    public void setExit() {
    216325    writer.exit();
    217     }
    218 
     326    writer.finish();
     327    }
     328
     329    /** Establish the current owner of this document.
     330     * @param owner the current AppendLineOnlyFileDocumentOwner
     331     */
    219332    public void setOwner(AppendLineOnlyFileDocumentOwner owner) {
    220333    this.owner = owner;
    221334    }
    222335
    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     */
    224340    public synchronized void setSpecialCharacter(char character) {
    225341    try {
     
    232348    }
    233349
     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     */
    234361    private synchronized String read(long start_offset, int l)
    235362    throws IOException {
     
    242369    }
    243370
     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     */
    244377    private synchronized void write(long start_offset, long end_offset, String str, int l)
    245378    throws IOException {   
     
    251384    }
    252385
     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. */
    253387    private class AppendLineOnlyFileDocumentElement
    254388    extends ArrayList
    255389    implements Element {
    256 
     390    /** Our parent Element. */
    257391    private Element parent;
     392    /** The offset to the end of our fragment(s) of text, in respect to the entire document. */
    258393    private long end;
     394    /** The offset to the start of our fragment(s) of text, in respect to the entire document. */
    259395    private long start;
     396    /** If we haven't been written to file yet, this contains the text fragment itself. */
    260397    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. */
    266400    public AppendLineOnlyFileDocumentElement() {
    267401        super();
     
    271405    }
    272406
    273 
    274407    /** Construct a new element, whose content is found in bytes start to end - 1 within the random access file backing this document.
    275      * @param  start the starting offset as a long
    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
    277410     */
    278411    public AppendLineOnlyFileDocumentElement(long start, long end) {
     
    284417
    285418    /** 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
    288422     */
    289423    public AppendLineOnlyFileDocumentElement(long start, long end, String content) {
     
    295429    }
    296430
     431    /** Add the given node as one of our children.
     432     * @param child the new child Element
     433     */
    297434    public void add(Element child) {
    298435        super.add(child);
     
    300437    }
    301438
     439    /** Having written the content to file this method removes it from the element. */
    302440    public void clearContent() {
    303441        content = null;
    304442    }
    305443
    306     /** This document does not allow content markup. */
     444    /** This document does not allow content markup.
     445     * @return always returns null
     446     */
    307447    public AttributeSet getAttributes() {
    308448        return null;
    309449    }
    310450
     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     */
    311454    public String getContent() {
    312455        return content;
     
    315458    /** Fetches the document associated with this element.
    316459     * @return the AppendLineOnlyDocument containing this element
     460     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument
    317461     */
    318462    public Document getDocument() {
     
    320464    }
    321465
    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     */
    323470    public Element getElement(int index) {
    324471        Element element;
     
    332479    }
    333480         
    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     */
    335484    public int getElementCount() {
    336485        return size();
    337486    }
    338487
    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     */
    340492    public int getElementIndex(int offset) {
    341493        int index = -1;
     
    362514    }
    363515         
    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     */
    365519    public int getEndOffset() {
    366520        if(parent != null) {
     
    375529    /** This method retrieves the name of the element, however names are not important in this document so the name is always an empty string.
    376530     * @return an empty String
     531     * @see org.greenstone.gatherer.util.StaticStrings#EMPTY_STR
    377532     */
    378533    public String getName() {
     
    380535    }
    381536         
    382     /** Fetches the parent element. */
     537    /** Fetches the parent element.
     538     * @return the parent Element
     539     */
    383540    public Element getParentElement() {
    384541        return parent;
    385542    }
    386543         
    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     */
    388547    public int getStartOffset() {
    389548        if(parent != null) {
     
    395554    }
    396555         
    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     */
    398559    public boolean isLeaf() {
    399560        return (parent != null);
    400561    }
    401562
     563    /** Establish the parent of this element
     564     * @param parent the parent Element
     565     */
    402566    public void setParent(Element parent) {
    403567        this.parent = parent;
    404568    }
    405569    }
    406 
     570    // AppendLineOnlyFileDocumentElement
     571
     572    /** This event is created to encapsulate the details of some change to the document. */
    407573    private class AppendLineOnlyFileDocumentEvent
    408574    implements DocumentEvent {
    409 
     575    /** The type of change event. */
    410576    private DocumentEvent.EventType type;
     577    /** The element this change occured to, or in. */
    411578    private AppendLineOnlyFileDocumentElement element;
     579    /** Another encapsulating class which contains further detail about the change itself. */
    412580    private AppendLineOnlyFileDocumentElementChange element_change;
     581    /** The length of the text fragment affected by the change. */
    413582    private int len;
     583    /** The offset within the document of the start of the change. */
    414584    private int offset;
    415585   
     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     */
    416592    public AppendLineOnlyFileDocumentEvent(AppendLineOnlyFileDocumentElement element, int offset, int len, DocumentEvent.EventType type) {
    417593        this.element = element;
     
    422598    }
    423599
     600    /** Retrieve the docment which generated this event.
     601     * @return the Document
     602     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument
     603     */
    424604    public Document getDocument() {
    425605        return AppendLineOnlyFileDocument.this;
    426606    }
    427607
     608    /** Retrieve the length of the change.
     609     * @return the length as an int
     610     */
    428611    public int getLength() {
    429612        return len;
    430613    }
    431614
     615    /** Retrieve the start offset of the change.
     616     * @return the offset as an int
     617     */
    432618    public int getOffset() {
    433619        return offset;
    434620    }
    435621
     622    /** Retrieve the type of change.
     623     * @return the type as a DocumentEvent.EventType
     624     */
    436625    public DocumentEvent.EventType getType() {
    437626        return type;
    438627    }
    439628
    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     */
    441634    public DocumentEvent.ElementChange getChange(Element elem) {
    442635        if(element_change == null) {
     
    446639    }
    447640
     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. */
    448642    private class AppendLineOnlyFileDocumentElementChange
    449643        implements DocumentEvent.ElementChange {
    450 
     644        /** This array always contains the one Element that was appended. */
    451645        private Element[] children_added;
     646        /** This Element array is always empty. */
    452647        private Element[] children_removed;
     648        /** The index of the affected element within its parents children. */
    453649        private int index;
     650        /** Construct a new AppendLineOnlyFileDocumentElementChange with the default 'append line' details. */
    454651        public AppendLineOnlyFileDocumentElementChange() {
    455652        children_added = new Element[1];
     
    458655        index = root_element.indexOf(element);
    459656        }
    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.
    461659         * @return an Element[] containing the added element
    462660         */
     
    464662        return children_added;
    465663        }
     664
    466665        /** This model does not allow elements to be removed.
    467666         * @return an Element[] containing nothing
     
    485684        }
    486685    }
    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... */
    489691    private class AppendLineOnlyFileDocumentPosition
    490692    implements Position {
    491 
     693    /** The offset within our document. */
    492694    private int offset;
    493 
     695    /** Construct a new position given an offset.
     696     * @param offset the offset as an int
     697     */
    494698    public AppendLineOnlyFileDocumentPosition(int offset) {
    495699        this.offset = offset;
    496700    }
    497 
     701    /** Retrieve the offset of this position.
     702     * @return the offset as an int
     703     */
    498704    public int getOffset() {
    499705        return offset;
    500706    }
    501707    }
    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. */
    503711    private class WriterThread
    504712    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. */
    506716    private boolean exit;
     717    /** When the writer thread is busy writing content to the file this flag is set to true. */
    507718    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). */
    508722    private Vector queue;
    509 
     723    /** Construct a new writer thread with an initially empty queue. */
    510724    public WriterThread() {
    511725        super("WriterThread");
     726        empty_queue = false;
    512727        exit = false;
    513728        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. */
    516733    public synchronized void exit() {
    517734        //print("WriterThread.exit() start");
     
    521738    }
    522739
     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     */
    523752    public boolean isStillWriting() {
    524753        return running;
    525754    }
    526755
     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     */
    527761    public void run() {
     762        exit = false;
    528763        running = true;
    529764        while(!exit) {
     
    542777            }
    543778        }
     779        else if(empty_queue) {
     780            exit = true;
     781        }
    544782        else {
    545783            synchronized(this) {
    546784            try {
    547                 //print("WriterThread.wait() start");
     785                print("WriterThread.wait() start");
     786                waiting = true;
    548787                wait();
    549                 //print("WriterThread.wait() complete");
    550788            }
    551             catch(Exception error) {
     789            catch(Exception exception) {
    552790            }
     791            print("WriterThread.wait() complete");
     792            waiting = false;
    553793           }
    554794        }
    555795        }
     796        print("WriterThread completely finished. Exiting.");
    556797        running = false;
    557798        if(owner != null) {
     
    560801    }
    561802
     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     */
    562807    public synchronized void queue(Element element) {
    563         //print("WriterThread.queue() start");
     808        print("WriterThread.queue(): " + ((AppendLineOnlyFileDocumentElement)element).getContent());
    564809        queue.add(element);
    565810        notify();
    566         //print("WriterThread.queue() complete");
    567     }
    568     }
     811    }
     812    }
     813    // WriterThread
    569814
    570815    // ***** METHODS WE ARE NOW IGNORING BECAUSE WE ARE VIRTUALLY READ-ONLY *****
    571816   
    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     */
    573820    public void addUndoableEditListener(UndoableEditListener listener) {}
    574821       
    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; }
    583831   
    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; }
    588836   
     837    /** Not implemented. Insert a text fragment into our document.
     838     * @param offset int
     839     * @param str String
     840     * @param a AttributeSet
     841     */
    589842    public void insertString(int offset, String str, AttributeSet a) {}
    590843
    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     */
    592848    public void remove(int offs, int len) {}
    593849
    594     /** Removes an undo listener. */
     850    /** Not implemented. Removes an undo listener.
     851     * @param listener UndoableEditListener
     852     */
    595853    public void removeUndoableEditListener(UndoableEditListener listener) {}
    596854   
    597     /** Renders a runnable apparently. */
     855    /** Not implemented. Renders a runnable apparently - whatever that means.
     856     * @param r Runnable
     857     */
    598858    public void render(Runnable r) {}
    599859
     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     */
    600866    static synchronized public void print(String message) {
    601867    Gatherer.println(message);
    602868    }
    603869
     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     */
    604876    static public void main(String[] args) {
    605877    JFrame frame = new JFrame("AppendLineOnlyFileDocument Test");
     
    616888    JButton read_button = new GLIButton("Read Huge File");
    617889    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));
    651891    content.setLayout(new BorderLayout());
    652892    content.add(new JScrollPane(text_area), BorderLayout.CENTER);
     
    655895    frame.show();
    656896    }
     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
    657963}
  • 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 */
    131package org.greenstone.gatherer.util;
    232
    333import 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 */
    538public 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     */
    642    public void remove(AppendLineOnlyFileDocument document);
    743}
     44
     45
     46
Note: See TracChangeset for help on using the changeset viewer.