Return to dictionary applet.


Dictionary Documentation

Written by Laura Menke and Wendy Miller
Last modified on August 4, 1997 by Wendy Miller

Contents

  • User Documentation
  • Purpose
  • Requirements - If having problems, read.
  • Contents of the User Interface
  • Choosing A Dictionary
  • Primary Operations
  • Listbox Operations
  • Saving
  • Technical Documentation
  • Setting up the Dictionary Program
  • Files Needed
  • ReadMe.txt
  • Client (read introduction)
  • Dictionary.class
  • StreamListener.class
  • Dict_titlePanel.class
  • Dict_mainInputPanel.class
  • Dict_featureValue.class
  • Dict_Submit.class
  • Dict_donePanel.class
  • Dict_loadDict.class
  • listframe.class
  • frame.class
  • Server (read introduction)
  • Server.class
  • Connection.class
  • Vulture.class
  • StreamListenerLisp.class
  • Lisp
  • Introduction
  • Description of Functions and Constants
  • Debugging and Declarations
  • Handling Files
  • Operations
  • Printing Messages to Files
  • Possible Improvements

  • Dictionary Program User Documentation

    Contents

  • Purpose
  • Requirements - If having problems, read.
  • Contents of the User Interface
  • Choosing A Dictionary
  • Primary Operations
  • Listbox Operations
  • Saving

  • Purpose

    The program allows a user to create and maintain a dictionary. A dictionary is a list of words with information about their part of speech, root, and other features described below. The operations allow a user to add, delete, lookup, and update entries. The software allows multiple users to choose the dictionary they wish to edit or edit the same dictionary. The dictionary records in the entry of a word the name of the person who made the last modification.

    Return to User Documentation Contents

    Requirements

    The program requires that the server and lisp programs be running. If the server is not running, you will be notified by a message frame when the html document is finished loading. If after loading a dictionary you do not receive a confirmation response, then the lisp program is not running. E-mail wmiller@cornell-iowa.edu a message saying that you would like to try the program, and she will be sure to have both programs running.

    Return to User Documentation Contents

    Contents of the User Interface

    Following is a brief explanation of the user interface's contents.

    Return to User Documentation Contents

    Choosing A Dictionary

    After loading the homepage and applet, a frame will pop up requesting the user to enter a dictionary. The user must place this frame somewhere on their screen by clicking the mouse button.

    To CHOOSE A DICTIONARY upon starting the program:

    1. Select one of the Choicebox options.
    2. Click on enter.
    The response will be a message confirming that the dictionary was loaded.

    To CHOOSE A NEW DICTIONARY while making modifications:

    1. Click on the new dictionary button.
    2. Select one of the Choicebox options.
    3. Click on enter.
    There will be two responses:
    1. A message saying that the former dictionary selected was saved.
    2. A message confirming that the dictionary was loaded.

    Return to User Documentation Contents

    Primary Operations

    To ADD a word to the dictionary:

    1. Choose add in the operation choice box.
    2. Complete the form. User name, number, word, and root are required.
    3. Click on submit.
    Possible responses are:

    To DELETE a word in the dictionary:

    1. Choose delete in the operation choice box.
    2. Complete the form. Number and word are required.
    3. Click on submit.
    Possible responses are:

    To LOOKUP a word in the dictionary:

    1. Choose LookUp in the operation choice box.
    2. Complete the form. Word is required.
    3. Click on submit.
    Possible response are:

    Return to User Documentation Contents

    Listbox Operations

    Listbox operations are available when the user performs a look up of the word or tries to perform the add or delete operations on a word and tense which already appear in the dictionary.

    Delete

    1. Click on one of the senses of the word to select it.
    2. Click on delete button.
    Possible responses are:

    Cancel Click on cancel button. Program returns you to the form.

    Update Click on update button. Program responds confirming that the word has been updated.

    Return to User Documentation Contents.

    Saving

    It is the user's responsibility to periodically save the dictionary. Any changes made will not be saved permanently until the user clicks done.

    To SAVE the dictionary click on the done button. A message confirming that the dictionary was saved will appear.

    Return to User Documentation Contents
    Return to Documentation Contents

    Setting up the Dictionary Program

    Contents

  • Files Needed
  • ReadMe.txt

  • Files Needed


    ReadMe.txt

    The Dictionary Software was created by Laura Menke and Wendy Miller 
    during the summer of 1997 at the University of Wisconsin-Milwaukee. 
    For any questions or comments please email: menke_ll@cslab.uwlax.edu 
    or wmiller@cornell-iowa.edu.
    
    To Install the Dictionary Software:
     
    1. Place in any directory. 
       (NOTE: If you want the dictionary software to be reached from a 
       web site, create a directory for the Dictionary software in you 
       public HTML directory.)
    
    2. You must change the path name in the three getDirectory() methods 
       in the file Server.java.  The methods are located at the bottom of 
       the Server, Connection, and StreamListenerLisp classes.  The path 
       names must be the full path to where the files for the Dictionary 
       software are located.
    
         The getDirectory() method looks like this:
        
    	   private String getDirectory(String file){
    	 	StringBuffer filepath = 
                       new StringBuffer("E:\\Users\\laura\\dictionary\\");
    		filepath.append(file);
    		return filepath.toString();
    	   }   
     
        Just replace the path name in the quotes.
    	(NOTE: It is important to use the double backslashes 
      		when installing on a Windows\DOS enviroment.)
    	
       YOU MUST RECOMPILE THE Server.java FILE!!! 
    
    3. You must also change a path name in the file lispprog.lisp.
       This path name will be the same path name you entered in the 
       Server.java file.
    
       Below is the line of code in lispprog.lisp you will need to 
       change. It appear in the at the beginning of the file.
    
    	(defvar *direct* "E:\\Users\\laura\\dictionary\\")
    
    
    To Run the Dictionary Software:
    
    1. You must start the java Server.
       A.) From a MS-dos window, you must be in the Dictionary 
           Software directory.  
           Then at the promt type:> java Server
       B.) From a Unix or Lynix, you must be in the Dictionary 
           Software directory.
           Then at the promt type:> java Server
    
    2. You must use a lisp interperter to load the lispprog.lisp 
       file which will then start the lisp program.
    	
    3. Now you can go to the browser to test the Dictionary.
       NOTE: Because java and LISP are communicating through 
             files, some tmp file will not be deleted if the 
             program stalls.  You can delete a the following 
             files in the Dictionary Software Directory when 
    	 the server is not running!!
    		
    	  A.  all .tmp files
    	  B.  all .lisp files
    	  C.  all files the look like Host server address 
    	      with a port appended to it.
    		For Example:
    			tigger.cs.uwm.edu9189 or localHost3874
    
    4. For more information, read the DictDocs.html file 
       (from a browser) that is in the Dictionary Software 
       Directory.
    
    
    To Modify the Dictionary HTML documents:
    
    You will want to make three changes at the top of the
    dictionary.html file.  
    
    1. There is a "last modified" line where you will want to 
       replace the appropriate E-mail address after "mailto:" 
       and also type new text for the link.
    
    2. The next line is a link back to the main document.  For
       example, if you include a link to the dictionary from your
       homepage then you should also include a link on the dictionary
       back to your page.  You will want to modify the link address and
       link text. 
    
    3. The last line is another "mailto:" link.  It is important that you
       include the E-mail address of the person who will be able to start
       up the server and lisp programs.  Guests to the page will then know
       who to contact in order to play with the program.
    
    If, for some reason, you change the name of the "dictionary.html"
    document then you should also one line in DictDocs.html.  There is
    a link at the beginning of the document to take guests back to the
    page containing the interface.
    
    To Add or Delete Dictionaries:
    
    Adding a dictionary requires you to modify the "listOfDict.txt" file.
    Just add the dictionary's name to the list.
    
    To delete a dictionary, there are two changes that need to be made. You
    need to remove the dictionary's name from the list in the "listOfDict.txt"
    file.   It is also necessary to delete the "****.table" file from the 
    directory which contains the Dictionary program.  If there is no 
    "****.table" file, then the dictionary had not been saved to a file.
    
    
    
    
    Return to SetUp Contents
    Return to Documentation Contents

    Dictionary Software Client Side

    1. Introduction
            This documentation describes the implementation of the client side of the dictionary software. This software was the first attempt for us at programming in Java.   We broke the clients side up into many classes. There are many things I would change about the design of this code.  For example I would not have sparated the interface into as many of classes as I did and I would have handled the events a little differently also.  The classes and a brief description of these classes are listed below.  The rest of the paper will take a deeper look into each of the classes. Also there is a section on how to update the files for dynamic choice boxes that are used in Dict_mainInputPanel.class.
                The Dictionary Client Software communicates with a server side java program which communicates with a lisp program  that manipulates the dictionary.  It sends the following types of messages to the server; C1.* to build the operation choice component, C2.* to build  partOfSpeech choice component, and dict.* to build the dictionary choice component. Also various lisp expression message are passed to the server which just pass them on to the lisp program.
     
                1. Dictionary.class

                2. StreamListener.class:             3. Dict_titlePanel.class:             4. Dict_mainInputPanel.class:             5. Dict_featureValue.class:             6. Dict_Submit.class:             7. Dict_donePanel.class:  
                8. Dict_loadDict.class:  
                9. listframe.class:             10. frame.class:  
     
     
                               
    1. Dictionary.class
                 This is the driver class for the Dictionary Software.  It is the driver because this class brings everything together. It creates a socket to communicate with the server. It creates all the panels that contain all the GUI components. Most importantly,  it handles all of the events  exceptions those from  listframe and frame classes.
                        The Dictionary class extends Applet. To initialize the applet the method init() is called.  This is the method where the Dictionary class creates the socket to communicate with the server. Below is the section of code that creates the socket and grabs the input and output stream from the socket. The call to initialize is within a try/catch block to catch the exceptions.
     
                                        try{
                                          s = new Socket(this.getCodeBase().getHost(),PORT);
                                          in = new DataInputStream(s.getInputStream());
                                          out = new PrintStream(s.getOutputStream());
                                          }

            init()  is also responsible for creating instances of Dict_titlePanel, Dict_mainInputPanel, Dict_featureValue, Dict_Submit, Dict_donePanel, and Dict_loadDict.  These classes contain the components that make up the Dictionary interface. It arranges these instance on the applet using GridBagLayout.  Finally, the init() method creates an instance of  StreamListener to  listen for messages from the Server and then process that information.
                       The event-handling code in the Dictionary software is a single long switch statement within the handleEvent() method.  The handeEvent() method is invoked by the system when an event is generated. For example it can be anything from a keyPress to ACTION_EVENT.  You can find a list of the different types of events in the book Java in a Nutshell, ORielly & Associates, Inc..
            This is the area of the code that needs to be changed in the event of switching to Java 1.1.
            The only events that are handled by the Dictionary code are ACTION_EVENTs. All others are handled by the operating system. ACTION_EVENTs are generated by the buttons; sumit, reset, done, and new dictionary.  If the event is handled by one of the four buttons cases below, the function will return true.  Else the function will return false and then the operating system will take over and try to handle the event. Below are the events that we defined to do something.
     
        Submit button from class Dict_Submit
            If the button clicked on  was the submit button from the Dict_Submit class, we check to to see if the selected item of the Choice component from the Dict_mainInputPanel was Add, Delete, or Lookup.  If the selected item was Add, call the checkingAdd() method. Else, if selected item was Delete, call the checkingDelete() method. Else, if selected item was Lookup, call the checkingLookUp() method.  checkingAdd(), checkingDelete(), and checkingLookUp() are all methods that check to make sure the right information is there that is needed by the dictionary before it is even sent to the server.  These methods will be explained in depth below.

        Reset button from class Dict_Submit
            If the button clicked on was the reset button from the Dict_Submit class, clear all the TextFields.  Notice that this event does not send anything to the server.
     

         Done button from class Dict_donePanel
            If the button clicked on was the done button from the Dict_donePanel class, send a message to the server to save the dictionary. The message sent to the server is in the form of a Lisp expression. An example of what Lisp will receive is shown below, where "health" is the name of the dictionary.
     
                            Example :  ("Save" ("health"))
     
     
         dictionaryButton from class Dict_donePanel ACTION_EVENT
              If the button clicked on was the dictionaryButton from the Dict_donePanel class, send a message to the server to save the current dictionary and then create an instance of Dict_loadDict which is a frame that asks for the name of a new dictionary.
     
                There are two more methods in the class Dictionary.  setDictionary() and getDictionary. setDictionary() is called in the Dict_loadDict class, it sets the private variable dictionary to the name to the dictionary the user wants to use.  getDictionary() returns a string which is the name of the dictionary that is currently being used.
     

    2. StreamListener.class
            This class extends Thread.  It's job is to loop forever waiting for inputs from the server.  Once it has received input from the server, it looks to see if the input was of type message.  If the input was of type message, this class then creates a frame object with the title of type message and then  reads from input one more time to get the message part of the frame. It then re-enables the submit, done, and dictionaryButton.  Once it has re-enabled the buttons, it resumes waiting for the next input.  Below is the code for the message input.

                If the input was not of type message, it then checks to see if the input was of type list. If the input is of type list, StreamListener then creates a  listframe object.  It passes the listframe object, the dictionary object, the title for the frame and a message.  Then StreamListener loops to read in from the server all of the items to add to the list in the listframe class. The submit, done, and dictionary buttons will not be re-enabled here. Below is the code for the list input.
      3. Dict_titlePanel.class
                This class extends Panel. It creates a Label object which says Medical Dictionary and places Label in the layout using GridBagLayout.  Now looking at it, using GridBagLayout is probably not the best Layout to use. The better Layout probably would have been flowLayout because it would be less coding and it is a simpilar layout.  With GridBagLayout we needed to set the constraints of the Label using the setConstraints() method.

    4. Dict_mainInputPanel.class
                This class extends Panel and has a GridLayout. It contains the main GUI component used for input in the Dictionary Software.  Dict_mainInputPanel creates instances of  TextFields, Labels, and Choice components.  Dict_mainInputPanel adds items to the Choice components dynamically by reading from a file that is on the server.  For this reason Dict_mainInputPanel must have access to a socket's InputStream and  OutputStream, which is passed to Dict_mainInputPanel in it's constructor method.  Below is the code for the operation Choice component with the description about the code embedded. It is the exact same for the partOfSpeech Choice component.

            The contents of files that are use for dynamically adding items to the Choice components must be arranged in a certain form. each file must start with a "!!" on the first line.  Any item that you want to be added to the choice component must be on it's own line. If you would open up the partOfSpeecht.txt file it would look something like the example below.
                            Example:       When the server side reads null, whichis the end of file marker, it  sends  null to the client side. However when you send null to the client side you must treat it as a string and check for it with  stringVariablename.equals("null"). 5. Dict_featureValue.class
        This class extends Panel and has a GridBagLayout.  This class creates TextFields for the feature and Value pairs.  It also creates Labels for the feature and value pairs.  The method setConstraints, sets the constraints of the TextFields and Labels.  If I were to do this differently I would not have used GridBagLayout, instead I would have use GridLayout because it is easier and less coding.
     

    6. Dict_Submit.class
             This class extends Panel and has a GridBagLayout. It creates Labels and Buttons for Submit and Reset and places them. The events that Submit and Reset give off should have been handled here instead of in the Dictionary. Nothing is wrong with handling the events in the Dictionary class, but on larger project it might be  slower. In fact if it we were to do this whole dictionary Software interface over I probably would not have separated the classes in this way. I probably would have combined Dict_titlePanel.class, Dict_mainInputPanel.class, Dict_featureValue.class, Dict_donePanel.class and Dict_Submit.class into one class. I still would have kept them all sparated into their own Panels though.
     

    7. Dict_donePanel.class
        This class extends Panel and has a FlowLayout.  It creates Labels and Buttons for Done and New Dictionary and places them.  The events that Done and New Dictionary button give off should have been handled here instead of in the Dictionary class. Again Nothing is wrong with  handling the events here, but on larger projects it might be slower.
     

    8. Dict_loadDict.class
        This class extends frame and has a BorderLayout. This class creates a Label, a Panel to hold a Button, and a Choice object whose items are added dynamically by reading them from a file..  This class  is also passed a connection to the Dictionary object.  The events of the Enter Button are handled in this class.  I handled the events by using the action() method instead of the handleEvent() method to avoid needing  a switch statement. When the user clicks on Enter, a message is sent to the Server to tell what dictionary the user would like to use.  Below is an example of the message:
                                                        Example: ("loadDict" ("Meg"))

    After it has sent the message to the Server, it also enables the Submit Button from the Dict_Submit class. Finally it hides and disposes of itself.  Else, if the user did not enter something in the TextField, this class creates a Frame object with an error message. Below is the code for handling the event.

    9. listframe.class
        This class extends frame and has a BorderLayout.  This class is passed a connection to the Dictionary object, a string that will be the title of the frame and a string that will be the message in the listframe.  This class creates a Label, a List, and Button objects.
           The items of the List object are added by the Dictionary class. This class is used for showing the senses of a word that is in the dictionary.  It also gives the users the choices of deleting a sense of the word, updating the sense of the word or just canceling the frame and moving on.
           The events are handled by the action() method.  Each button gives off an ACTION_EVENT that is then interpreted by the action().  Below is the code of the action() method.
      The send_to_file() method is special to update. It is only here that an update message can be sent to the server.  The checkingUpdate() method checks to make sure that all the information that is needed to make an Update is present.  The checkNumber() method  is the first method to be called in case of an Updated button event.  It checks to make sure that the number in the wordNumber field of the Dict_mainInputPanel.class corresponds to the number of a sense of a given word.  If it does not, an error message occurs and  methods checkingUpdate() and send_to_file() will never be called.
     

    10. frame.class
        This is a generic message frame class which extends frame and  can be used in any java program.  When you create an instance of this class you pass it a string which will be the title and then you pass it a string that will be the the message.  This frame will automatically pack itself to fit the size of the message.  Below is part of the constructor which shows the way you should pass the title and the message
                                                Example:
                                                                public frame(String title, String message){
     
    When the users clicks on the Okay button.  The frame hides and then disposes of it's self.

    Return to Client Documentation Introduction
    Return to Documentation Contents



    Dictionary Software Server Side
    Return to Server Documentation Introduction
    Return to Documentation Contents

    Lisp Documentation

    Contents

  • Introduction
  • Description of Functions and Constants
  • Debugging and Declarations
  • Handling Files
  • Operations
  • Printing Messages to Files
  • Possible Improvements

  • Introduction

    The Lisp component of the Dictionary program can be divided into four main sections. The first section includes debugging tools and the creation of the pathname and hash table constants. The next section contains functions which handle the file communication with Java. The third section includes the functions needed to maintain the dictionaries. The last section contains three functions that print information to a file in a format that the Java client is programmed to understand.

    There are a few things to remember about this code. The first is that Java is waiting for a reply for nearly every submission of data. So Lisp always completes its process of a submission by printing a response to its output file. This is why many functions make a call to simpleoutmess, simpleoutdict, or sendList. Another suggestion is to read the section called "Possible Improvements" before looking at the code in too much detail. It will help you see what some of the problems are so that you may have those in mind while looking at the code.


    Description of Functions and Constants

    Following is a brief explanation of the functions and constants in each section.

    Debugging and Declarations

    *test* and printMess
    The function printMess and the constant *test* were used to debug the files being used to communicate with Java. If *test* is sent to "t", when printMess is called after a file is accessed, the path and file will be printed on the screen.

    *direct*
    The constant *direct* is used to set the pathname of the directory where the files are located.

    *tables*
    The hash table *tables* is used to keep track of the multiple dictionaries. The key is the script name of the hash table, the value is the hash table.

    Return to Lisp Documentation Contents

    Handling Files

    run()
    This is the function which calls the program. It loops and, unless the "clients.tmp" file has been created by Java, calls the readClient.

    readClient()
    This function reads the clients file and sets it to the constant clientlist. Unless the list of clients is empty, the function calls scanfiles to process data for each client.

    scanfiles (dalist)
    Scanfiles is a recursive function which, for each client listed, creates a constant called *infile* and then calls check. *infile* is the name of the file that Java client has printed information to for Lisp to process.

    check ()
    Check's purpose is solely to check to see if Java has created the client's temp file, "clientsAddress.tmp", signaling that Lisp should read the file "clientsAddress" for information to process. If the file has been created, then inout is called.

    inout ()
    This function reads in the information from *infile*. Unless there was an error and data is nil, then the function does the following: sets *outfile* to "clientsAddress.lisp", clears *infile*, deletes *tempfile*, and calls determinop. After determinop has finished, inout calls the createtmp function to create the "clientsAddress.lisp.tmp" to signal to Java that it needs to read "clientsAddress.lisp".

    createtmp (file)
    Createtmp creates a blank file.

    clearfile (filename)
    Clearfile clears the specified file.

    Return to Lisp Documentation Contents

    Operations

    determinop (data)
    This function sets *command* to action the client wants lisp to perform. It sents *data to the rest of the information. If the command is either to load or save a dictionary, then it calls the appropriate function. Any other command results in a call to the function operation.

    operation ()
    This function performs a number of "setf"s and calls the next function based on the value of *command*. *dict* is set to the name of the dictionary, *words* is set to the dictionary's hash table, *wordinfo* is all the information about the word, and *word is the word. The function calls the add, del, LookUp, Update, and sendAllsense functions.

    loadDict ()
    This function sets *dict* to the name of the dictionary. It creates a hash table for the dictionary and sets the table as a value in the hash table, with the key being the script name of the dictionary. The function checks to see if there is a file of the same name as the dictionary with a ".table" extension. This file is where the dictionary entries are saved. If the file exists, then loadDict2 is called. Otherwise, the function sends a message saying that the dictionary loaded has no entries.

    loadDict2 ()
    loadDict2 loads the file where a dictionary is saved (dictionaryName.table) into a hash table and sends a message to the client confirming that the dictionary was loaded.

    add (d)
    This function checks to see if the word or sense of the word exists. If the word or sense has not yet been added to the dictionary, then it calls the appropriate function. If the word and tense have already been entered then a message is returned to the client.

    simpleAdd (d)
    simpleAdd adds a new word to the dictionary and sends a message to the client.

    tenseAdd (d)
    tenseAdd adds a new sense of a word to the dictionary and sends a message to the client.

    LookUp (d)
    This function checks to see if the word and sense submitted are in the dictionary. If not, then a message is returned to the client which says that either the word or the sense is not in the dictionary. Else, the function calls sendList to output to the client the entire entry for the word.

    del (d)
    del is similar to LookUp in that it first checks to see if the word and sense submitted are in the dictionary. If the word and sense has been entered then the finishDelete is called.

    finishDelete (d)
    Function deletes the sense from the hash table. If no more senses remain, it removes the entire word from the dictionary and sends a message to the client.

    update (d)
    This function substitutes the new information entered in the interface for an entry which already exists. A message is returned confirming the update.

    sendAllsense (d)
    sendAllsense is called when the user leaves the number for sense empty on the interface. The function checks to see if there is an entry for the word. If an entry exists then the entry is sent to the client using the sendList function, else a message is sent to inform the client that the word is not in the dictionary.

    exitRoutine ()
    This function sets *words* to the name of the dictionary. It calls savewords to save the hash table to a file and sends a message to the client.

    savewords (z)
    savewords prints the dictionary's hash table to a file. The file is named using the name of the dictionary and the extension ".table".

    Return to Lisp Documentation Contents

    Printing Messages to Files

    NOTE: It is important to include a command to remove newline characters when printing to the file because Java will have difficulties reading the file. An example of this from the simpleoutdict function is

    (remove #\newline (format str outmess *dict*))

    simpleoutdict (outmess) and simpleoutmess (outmess)
    These functions are designed for sending messages to the client. It prints a token "message" on the first line of the *outfile* and the message on the next line. If you include "~A" in the string sent to the function, simpleoutdict will print the name of the dictionary in your message and simpleoutmess will print the word. An example of this, with dog being the word, is

    (simpleoutmess "The word ~A is not in the dictionary.")

    which will print to *outfile*

    message
    The word dog is not in the dictionary.

    sendList (mess)
    This function is designed for the purpose of sending the Java client a list of entries for a word. It prints a token "list" and the entries for the word to *outfile*.

    Return to Contents


    Possible Improvements

    One of the things that I wish I had the time to clean up deals with the overuse of "setf." In our early confusion, we used "setf" every time we wished to assign something to a symbol. As the code is currently, we have some functions to which a parameter is passed and these parameters have also been set to a symbol. The code needs to be more consistent.

    Return to Lisp Documentation Contents
    Return to Documentation Contents