B2 Interface Documentation
Laura Menke and Wendy Miller
August 1997
Contents
ReadMe.txt
The B2 Interface and Server 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 B2 Interface and Server
1. Unzip B2.zip in any directory.
(NOTE: If you want the B2 software to be reached from a
web site, create a directory for the B2 software in you
public HTML directory.)
2. You must change the path name in three places in the B2Server.java
file.
A. The first two places are at the top of the B2Server class
The two lines of code are shown below.
String defaults = new String("C:\\InetPub\\wwwroot\\B2\\B2\\scenarioChoice.txt");
String directory = new String("C:\\InetPub\\wwwroot\\B2\\B2\\");
B. The last path name that must be change is the path name to
the Lisp program that works with the interface.
CHANGE!!
lisppr = lisprt.exec("E:\\Programs\\clisp-win32\\lisp.exe -q -M E:\\Programs\\sneps-2.3.1\\lispinit.mem -i C:\\InetPub\\wwwroot\\B2\\B2\\mmio.lisp");
YOU MUST RECOMPILE THE B2Server.java FILE!!!
C. The location of files for the lisp process must be
changed in the file mmio.lisp in the B2 directory.
(defvar *path* "C:/InetPub/wwwroot/B2/Discourse-latest/")
To Run the B2 Interface and Server.:
1. You must start the java Server.
A.) From a MS-dos window, you must be in the directory where you installed the B2 Interface.
Then at the promt type:> java B2Server
B.) From Windows, you can just double click on the startb2.bat file.
C.) From a Unix or Lynix, you must be in the directory where you installed the B2 Interface.
Then at the promt type:> java B2Server
Return to B2 Documentation Contents
B2 Client Side Documentation
1. Introduction
This document describes the implementation of the client side of the
the B2 interface. There are four classes that belong to the client side
of the B2 interface. Below is list of the classes with a brief
description of each of the classes. Each class will be discussed
fully later in the document.
1. b2.class
This class create all the objects that are in the B2 interface.
The interface is broken up in to many different panel. Some of the interface
is created dynamically. Details on how to create the files
for the dynamic Choice components will follow the explanation of
the buildChoice() method. Each panel will be discussed in
depth. This class creates a socket to communicate with the server on a
given port. This class also handles some of the events of the b2
interface which will also be discussed in depth later. We will also discuss
some of the major methods that are called by the browser such as init(),
start(), and stop().
2. StreamListener.class
This class is just a thread that listens for input from the Server.
3. b2Scenario.class
This is a panel that dynamically creates TextField and Choice components
by sending a message to the Server to open, read and then send
back the information in a file. Read the section on b2Senario
Files to learn how to create files to be used with this class.
4. saveDeleteScenario.class
This is a generic frame that is used to either save or
delete a scenario.
5. MiscInfo.class
This is a generic frame that can be used any time B2 needs to
input text information. For example, it is now, used to submit a name of
a file to load scenarios.
6. messageFrame.class
This is a generic class that will display a message in a frame that
disposes of itself when the Okay button is clicked on.
This B2 Java client communicates with a Java Server which in turn communicates
with a Lisp Process by grabbing the Process's standard input and output
streams. (Read the B2 Server Side Documentation for further information.)
To look at the code open the .java files. The above classes are
in their own .java file, except the StreamListener.class is in the b2.java
file
2. b2.class
This class extends Applet.
It creates a socket to communicate with the server. It creates all
the panels that contain all the GUI components. It handles the events of
the components in this class. Below we will discuss the important methods
of this class starting with the init() method.
I. init() method
To initialize the applet the method init()
is called. This is where the b2.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. This is done
within a try/catch block to catch and exceptions.
try {
//Here we are
creating a socket to connect to the server.
s = new Socket(this.getCodeBase().getHost(),PORT);
//Here we get the
input and output streams from the socket.
in = new DataInputStream(s.getInputStream());
out = new PrintStream(s.getOutputStream());
//Here we create
the Scenario panels that build themselves dynamically
//by reading files
on the Server. Therefore we must send them the
file to read,
// the b2applet,
the name of the panel, and
//the input and
output streams so that they can communicate with the server.
historyScenario = new b2Scenario("b2History.txt",this,"History",in,out,identifier);
physicalScenario = new b2Scenario("physical.txt",this,"Physical
Findings",in,out, identifier);
testScenario = new b2Scenario("tests.txt',this,"Tests",in,out,identifier);
}
catch(IOException e) {this.showStatus("Sorry Server
is not running. Try again later");}
catch(Exception e) {System.out.println("exception");}
Also within the try/catch block, the init() method
creates three instances of b2Scenario
objects; historyScenario, physicalScenario, and testScenario. It creates
them within the try/catch block because the b2Scenario objects need to
know what the socket's input and outstreams are so that it can communicate
with the server and if an exception occurs.
Next the init() method sets the layout of the applet
to GridBagLayout. It then calls three methods that create the main
input panel of the b2 interface. The methods are listed below with
their descriptions.
Main Input Panel
makeTitlePanel(): This method creates the titlePanel panel
and sets the panels layout to GridBagLayout. It then creates the Label
that says Case Study and adds it to the panel.
makeSelectionPanel(): This method creates the selectionPanel
panel and sets the panels layout to GridBagLayout. It then creates Labels
for the three choice components ("Select a scenario", Select a topic",
"Save, Load, or Delete") and the Button ("Select a task"). ( Next it creates
the Choice components and calls the method buildChoice()
for each Choice. buildChoice() is the method that dynamically
adds items to the Choice components. (buildChoice() will be discussed later.)
The buildChoice() method is passed the topic.txt file for the topicChoice,
scenarioChoice.txt file for the scenarioChoice, and options.txt file for
the optionsChoice. After creating the Choice components this method
then creates the Story Problem button. Finally it adds all the components
to the selectionPanel.
makeDialogPanel(): This method creates the dialogPanel panel
and sets its layout to GridBagLayout. It then creates two TextAreas. The
first TextArea is b2dialog and it is created to the size of 20 rows by
50 columns. This TextArea is set to be not editable. The b2dialog
TextArea is used to keep track of the dialog between the user and B2. The
second TextArea is dialog and it is created to the size of 5 rows
by 50 columns. This TextArea is placed directly under the B2dialog TextArea
in the dialogPanel. The dialog TextArea is editable and is where
the users types in her response. When the user presses return, the information
that she typed in the dialog TextArea is then echoed up to the b2dialog.
The init() method then calls three
more methods that create the Summary area of the B2 interface. The
methods and their description are listed below.
Summary Area
makeSummaryPanel(): This method creates the summaryTitlePanel
panel and sets the panels layout to GridBagLayout. It then creates the
Label that says Summary and adds it to the panel.
makeProbPanel(): This method creates the probPanel panel. It
sets the panel's layout to FlowLayout and sets the font. The probPanel
hold the components that make up the "Probability of Gallstones is 10%"
sentence. It first creates a Label for "Probability of". Then
it create a Choice component that contains a list of topics. The
items of the Choice component are dynamically added by calling the buildChoice()
method and passing it the topics.txt file. Next it creates a Label
for "is" and a Button for the user to click on to get the answer.
Finally it creates a TextField that is not editable for the answer to appear
in and then adds all the components to the probPanel panel.
makeBestTestPanel(): This method creates the bestTestPanel panel.
It sets the panels layout to FlowLayout and sets the font. The bestTestPanel
holds the components that make up the "Best test for ruling in Gallstones
is HIDA" sentences. It first creates a Label for "Best test for".
Then it creates a Choice component and adds two items to it: "ruling in"
and "ruling out." Next it creates diagnosis2Choice Choice component and
calls the buildChoice() method, passing
it the topics.txt file. Then it creates a Button for the user to click
on to get the answer. Finally it creates the TextField that is not editable
for the answer to appear in and then adds all the components to the bestTestPanel
panel.
Next the init() method calls two methods
that create the Scenario area of the B2 interface. The methods
and their descriptions are listed below.
Scenario Area
makeScenarioTitlePanel(): This method creates the scenarioTitlePanel
panel and sets the panel's layout to GridBagLayout. It then creates the
Label that says "Scenario Builder" and adds it to the panel.
makeScenarioCheckPanel(): This method creates the scenarioCheckPanel
panel and sets the panel's layout to GridBagLayout. It creates the
"Go To:" Label. It creates a CheckBoxGroup that will group the checkboxes
together. Then this method creates three checkboxes; "Medical History",
"Physical Exam", and "Tests". The Medical History checkbox is set to true.
This method also creates an identPanel to hold an identifierLabel for "Save
scenario as:", and to hold a TextField for the user to enter the name they
want the scenario to be saved as. Then this method creates a Submit Button
that will submit all the information from the b2Scenario objects.
Finally, this method adds all of the components to the scenarioCheckPanel
panel.
Next the init() method create a panel that houses
all of the b2Scenario objects and add the historyScenario object to it.
Then the init() method calls the setPanelConstraints() method
to set the constraints of all the panels and add them to the applet.
Finally, the init() method creates a streamlistener object which
will just loop while listening for input from the server.
II. start() method
The start() method
is called after the b2 applet has been initialized, when a user comes back
to the page after leaving, or after the user resizes the page. In
the B2 applet, we defined the start() method to send a message to
the server requesting it to restart the Lisp process, only if the applet
has been stopped by the stop() method. Besides having it send a
message to the server, we also clear the two dialog areas and the identifier
TextField.
public void start(){
if(stopped){
//set
the stopped boolean to false
stopped = false;
//clear
the dialog areas.
b2dialog.setText("");
dialog.setText("");
//clear
the identifier TextField.
identifier.setText("");
//send
message to server to restart the Lisp process.
out.println("*start*");}
}
III. stop() method
The stop() method
is called every time the user leaves the page or the user resizes the page.
In the B2 applet we define the stop() method to send a message to
the server to stop the Lisp process. It also sets the stopped variable
to true.
public void stop(){
//set
the stopped boolean to true
stopped = true;
//send
message to server to stop the Lisp process.
out.println("*stop*");
}
IV. buildChoice() method
The method buildChoice()
sends a message to the server requesting information from a file whose
name was passed to buildChoice() along with a Choice component. The
information in the file will be the items for the choice component.
The server will first send over the start flag "!!", to tell the buildChoice()
method that the next items that will be coming over the stream will be
the items to add to the Choice component. The buildChoice() method
will continue to loop and add Choice components until the server sends
null. The purpose of this method is to add items to a new Choice component.
However, if this method is called for an existing choice component, then
it will add more items to the existing list.
//This is the operation that Dynamically
adds the items to the Choice components.
public void buildChoice(Choice component,String fname){
String line = new String();
try{
//Send message to server to
open a buildComponents file
out.println("*component*");
//Send the name of the file
to be opened.
out.println(fname);
//Loop until receive a message
from server
while((line = in.readLine()) == null){;}
//Check to make sure it is
the start flag.
if(line.equals("!!")){
//Loop;
read in each item adding it to the Choice component until
// message from server is null.
while(!(line
= in.readLine()).equals("null")){
component.addItem(line);
}
}
else messageFrame tmp2 =
new messageFrame("Error", "Error in tranfering data to build choice components");
}catch(IOException e){System.out.println("IOException occurred in buildChoice
method");}
}
If the "!!" wasn't the first message from the server
an error has occurred and a messageFrame object is created with an error
message saying there was a error in tranferring data to the buildChoice()
method..
The contents of the Choice
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. Do not included any blank
spaces (at the end) or blank lines. If you would open up the file it would
look something like the example below.
Example:
When the server side reads null, that is
the end of file marker. The server then sends null to the client
side. However when you send null to the client side, it must be treated
as a string and tested for with stringVariablename.equals("null").
V. set_Constraints() method
The method set_Constraints() method sets
the contraints for the GridBagLayout and adds the items to their containers.
VI. handleEvent() method
The event-handling
code in the B2 software is a single long switch statement within the handleEvent()
method. The handleEvent() 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.
One
case in the switch statement that is handled, is the ACTION_EVENT.
Buttons, choice, and checkboxes, all generate ACTION_EVENT events.
Another case in the switch
statement is for KEY_PRESS events. When the user is in the dialog area
and presses return, this event is captured and handled by the handleEvent()
method. If either one of the cases in the switch statement handled the
event the function will return true. Otherwise 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.
taskButton Button ACTION_EVENT
If the user clicked on the taskButton Button
it sends a message to the server in the form of a Lisp Expression
Example: ("select" "task" "story problem")
topicChoice Choice ACTION_EVENT
If the user selected a item from the topicChoice
Choice component, it sends a message to the server with the item the user
chose in the form of a Lisp Expression.
Example: ("select" "topic" "Gallstones")
scenarioChoice Choice ACTION_EVENT
If the user selected a item from the scenarioChoice
Choice component, it sends a message to the server with the item that the
user chose in the form of a Lisp Expression.
Example: ("select" "scenario" "retired postal worker")
submit Button ACTION_EVENT
Users must give each scenario a unique id. If
the ID is the same as one of the items in the Choice component, then create
a messageFrame object with an error message that tells the user that scenario
name already exists. Else, if the word is not the same as one of
the items in the Choice component, add the word as a new item in the scenarioChoice
component. After verifying the ID, it sends a message to the server
that contains all the information from the History, Physical, and Test
b2Scenario objects.
Example:
("submit" "scenario" ("id" "young boy")
("history" ("Age" "12")
("Sex" "Male")
("Anorexia" "Absent")
("Vomiting" "Unknown")
("Diarrhea" "Absent")
("Obstipation" "Present")
("Similar Prior Symptoms" "Present"))
("exam" ("Temperature" "101")
("White Blood Count" "2344")
("Rigidity" "Absent")
("Guarding" "Absent")
("Rebound Tenderness" "Unknown")
("Abnormal Bowel Sounds" "Absent")
("Rectal Tenderness" "Unknown")
("test" ("US-GALLSTONES" "Not done")
("CT" "Positive")
("US-MURPHY-SIGN" "Not done")
( "US-THICK-GB-WALL""Positive")
("US-CHOLECYSTITIS" "Not done")
("ULTRASOUND" "Positive")
("HIDA" "Positive"))))
historyCheckbox, examCheckbox, and testsCheckbox
CheckBox ACTION_EVENT
If the user clicked on the historyCheckbox, examCheckbox, or testsCheckbox,
remove the components currently displayed on the scenariopanelPanel. Then
add either the historyScenario, physicalScenario, or testScenario object
to the scenariopanelPanel, depending on which item they chose. Finally
call the validated() method on the scenariopanelPanel to update
the scenariopanelPanel displayed in the applet. The code for the
historyCheckbox is shown below.
else if(event.target == historyCheckbox){
//remove all components from scenariopanelPanel
scenariopanelPanel.removeAll();
//add historyScenario to scenariopanelPanel
scenariopanelPanel.add(historyScenario);
//must call validate() for the Applet
to be updated!!!!
scenariopanelPanel.validate();
return true;
}
probButton Button ACTION_EVENT
If the user clicked on the probButton, it sends a message to the server
in the form of a Lisp Expression.
Example: ("request" "summary" "probablity" "gallstones" "*prob*")
testButton Button ACTION_EVENT
If the user clicked on the testButton, it sends a message to the server
in the form of a Lisp Expression.
Example: ("request" "summary" "best test" "ruling in" "gallstones" "*test*")
optionsChoice Choice ACTION_EVENT
If the selected item is "Save a Scenario" or "Delete a scenario"
create a saveDeleteScenario object to get the filename and scenario
id. If the selected item is "Load a Scenario File", create a MiscInfo
object to input the name of the file. Below is what this section of code
looks like.
else if(event.target == optionsChoice){
if(optionsChoice.getSelectedItem().equals("Save
a Scenario"))
saveDeleteScenario tmp =
new saveDeleteScenario("Save","To
Save a Scenario:","Enter a file Name:", "Choose a scenario:",this);
else if(optionsChoice.getSelectedItem().equals("Delete
a Scenario"))
saveDeleteScenario tmp2=
new saveDeleteScenario("Delete","To
Delete a Scenario:","Enter a file Name:","Choose a scenario:", this);
else if(optionsChoice.getSelectedItem().equals("Load
Scenario File"))
MiscInfo tmp3 = new MiscInfo("Load","To
Load a Scenario File:","Enter a file name:", this);
return true;
}
Return Key KEY_PRESS
If the key pressed was the return key (asci value 10) append the information
that is in the dialog TextArea to the b2dialog TextArea. Then send all
of the information that is in the dialog TextArea to the server in the
form of a Lisp Expression. Finally clear the dialog TextArea.
An example of the message sent to the server is shown below.
Example: ("text" "Tell me a story")
VII. rebuildScenarioChoice() method
This method
is only called from within the StreamListener class. It removes the old
scenarioChoice Choice component from the selectionPanel. Then it creates
a new scenarioChoice component. The server sends rebuildScenarioChoice()
the items to add to scenarioChoice. Next it sets the constraints
of scenarioChoice component and adds scenarioChoice to the selectionPanel.
Finally the validate() method is called on selectionPanel to update
it in the applet.
3. StreamListener.class
This class extends Thread.
Its job is to loop forever waiting for inputs
from the server. Once it receives input, it checks to see if the input
is one of the following cases and then does the described action.
-
"!!" calls the rebuildScenarioChoice()
method in the b2.class
-
"*prob*" sets the probField in
the class b2. It uses the next input from the server to update the
field's value.
-
"*test*" sets the testField in the class
b2. It uses the next input from the server to update the field's
value.
-
"*text*" appends the b2dialog
in the class b2. It uses the next input from the server to
append the b2dialog's text area.
-
"*inform*" creates a messageFrame object. It uses the next
input from the server to display a message in the object.
-
"*requestinfor*" creates a MiscInfo object. It uses next input
from the server to display a message in the object.
This is the class that must be changed if to handle
another token or flag from the server.
4. b2Scenario.class
This is a generic class that extends Panel.
It gets the information that it needs to create its components from the
file that was passed to it in its constructor. Besides the file, b2Scenario
is also passed: a connection to a b2 object, a string that will be
the title of the panel, and the input and output streams to communicate
with the server.
The b2Scenario() constructor first sets the
layout of the b2Scenario panel to BorderLayout. Then it grabs all of the
information that was passed to it. Next it creates the titlePanel Panel
for the titleLabel. Then it creates the titleLabel with the title
it was passed and adds it to the titlePanel. Next it creates the
componentPanel to house all of the components that were created.
The componentPanel has a GridLayout layout and a Helvetica font. Next the
callToServer() method is called. Below is a description of
the method callToServer() and important methods that callToServer()
calls.
callToServer() method: This method begins by sending
the flag "*component*" to tell the server that it should call openBuildComponents
and that the following input will be the name of the file it has to open.
Then callToServer() goes into a listening mode. It begins listening for
the start flag "!!" from the server. Once it has found the start flag,
it begins to loop reading a line at a time from the server until it reads
in "null". It processes each line looking for three flags; *TextArea*,
*Choice*, and *specialChoice*. If the line contains the *TextArea*
flag, the makeTextArea() method is called with the next line input
from the server. If the line contains the *Choice* flag the makeSimpleChoice()
method is called with the next line input from the server. And finally
if the line is equal to the *specialChoice* flag the makeSpecialChoice()
method is called with the next line input from the server.
makeTextArea() method: This method creates a TextField
and adds it to the array of TextFields called text[]. Next it creates
a Label object to label the TextField, with the string that was passed
to makeTextArea(). It also keeps track of the label of the
textField by putting it into a paralle array called textString[].
Then it adds the Label to the componentPanel. Finally, the TextField is
added to the componentPanel.
makeSimpleChoice() method: This method creates a Choice
component and adds to it three Items: Unknown, Present and Absent and stores
it in an array of Choice components called choice[]. It also creates
a Label to label the Choice component with the String that was passed to
makeSimpleChoice(). It then puts the label in a parellel
array called choiceString[] to keep track of the Choice component. Both
the Label and Choice components are added to the componentPanel.
makeSpecialChoice() method: This method is used to create
Choice components. This method first creates a Label from the string that
was passed to it and adds it to the componentPanel. Next it places
the name of the label in the choiceString[] array. Then it creates
the Choice component and adds it to the choice[]. Next it adds items to
the Choice component that it reads in from the Server until it reads the
end flag "e!!". Finally, it add the Choice component to the componentPanel.
private void makeSpecialChoice(String line) throws IOException{
//Method that creates Choice
and also adds X number of Items and puts it into an array of Choices.
//It also keeps track ot the
name to the choice by a paralle array.
//Places component in the
componentPanel.
//Uses same Choice and name
array as method makeSimpleChoice().
componentPanel.add(new Label(line));
choiceString[j] = line;
choice[j] = new Choice();
while(!(lines = in.readLine()).equals("e!!")){
choice[j].addItem(lines);}
componentPanel.add(choice[j]);
j++;
}
Another important method is the submit() method.
This method gathers all of the information from all of the components and
returns the information as a string in the form of a Lisp expression. First
it loops through the textString[] and text[] arrays in parallel gathering
the TextField information. Then it loops through choiceString[]
and choice[] arrays in parallel gathering all the information from the
Choice components. An example of the string that the submit() function
returns is shown below.
Example"
" ("history" ("Age" "12") ("Sex" "Male") ("Anorexia" "Absent") ("Vomiting"
"Unknown") ("Diarrhea" "Absent") ("Obstipation" "Present") ("Similar Prior
Symptoms" "Present")) "
A string is passed to the submit() method and
is used as a title for that section of information. In this example,
the string that was passed to submit() was "history".
b2Scenario files
To create a file to be used with the b2Scenairo class it is important
that if follow the following format: Each file begins with a start flag
"!!" and every piece of information be on a separate line. For example,
to create a simple Choice component with "Unkown", "Absent" and "Present"
as the items, place on one line the flag "*Choice*" and then on the following
line place the label that you would like to appear next to that Choice
component.
To create a Choice component with any other items,
place (on sparate lines) the flag "*specialChoice*" the label that
you would like to use for that Choice component and then each item that
you want to be added to the Choice component. After you have entered in
all the items, the last line should be the end flag, "e!!"
To create a TextField component, place on one line
the flag "*TextArea*", and then on the next line place the label that you
would like to use for that TextArea.
An example of a file that contains all the flags
is shown below.
Example file:
!!
*TextArea*
Age
*specialChoice*
Sex
Female
Male
e!!
*Choice*
Anorexia
4. saveDeleteScenario.class
This class is used for saving or deleting
scenarios. It extends Frame.
In addion to Labels, Choice, and
TextArea components, this class creates an Okay Button and a Cancel Button.
The Cancel Button, when clicked on, hides and disposes of the frame.
The Okay Button, when clicked on, checks whether the flag is equal to "Save"
or "Delete" and sends the appropriate message to the server in the
form of a Lisp expression. Below is the code for an Okay Button click.
if(e.target == enter){
if(flag.equals("Save")){
b2applet.out.println("(" + "\"" + "submit" + "\"" + "
" +
"\"" + "scenario"
+ "\"" + " " + "(" + "\"" + "save" + "\"" + " " +
"\"" + textfield.getText()
+ "\"" + ")" + "(" +
"\"" + "id" + "\""
+ " " + "\"" + selectScenario.getSelectedItem() + "\"" + "))");
}
else if(flag.equals("Delete")){
b2applet.out.println("(" + "\"" + "submit" + "\""
+ " " +
"\"" + "scenario"
+ "\"" + " " + "(" + "\"" + "clear" + "\"" + " " +
"\"" + textfield.getText()
+ "\"" + ")" + "(" +
"\"" + "id" + "\""
+ " " + "\"" + selectScenario.getSelectedItem() + "\"" + "))");
}
Example output to server:
This message causes the Lisp process to save the named scenario to
the file.
Flag = "Save"
("submit" "scenario" ("save" "filename") ("id" "postal worker"))
This message causes the Lisp process to delete the named scenario
from the file.
Flag = "Delete"
("submit" "scenario" ("delete" "filename") ("id" "postal worker"))
To create an instance of this class you must pass it
four strings and the b2 object. The first string is used for the title
of the Frame and also for the flag that determines which event to do upon
an okay button click. The second string is the command string for
telling the user what to do. The third string will label the TextField
and the fourth string is used for labeling the Choice component.
The b2 object is needed so that the class has access to the input and output
streams to the server.
5. MiscInfo.class
This is a generic frame
class that has a TextField for information input. At creation you
pass it a frame title, which is used for the frames flag, a message to
tell the user what to do, and a message to label the TextField. You
also pass it the b2 object so that MiscInfo will have access to the servers
input and output streams. This class also creates two Buttons: Okay and
Cancel. When the Okay Button is clicked, the frame does what the
flag specifies it to. An example of what types of flags are defined
in this class is shown below.
if(e.target == enter){
//To handle events of the different MiscInfo
you distinguish them by their frame title.
//flag is the title of the frame that is currently
being used.
if(flag.equals("Load")){
b2applet.out.println("(" + "\"" + "submit" + "\"" + "
" +
"\"" + "scenario"
+ "\"" + " " + "(" + "\"" + "load" + "\"" + " " +
"\"" + textfield.getText()
+ "\"" + "))");
}
else if(flag.equals("Request")){
}
this.hide();
this.dispose();
return true;
Example output to server:
This message causes the Lisp process to load a scenarios from a
file.
Flag = "load"
("submit" "scenario" ("load" "filename"))
As you can see the "Request" flag has not been defined yet.
You may also define more flags in this section of code. After the flag
has been handled, the frame is then hidden and disposed of.
The Cancel Button hides and disposes of the frame.
6. messageFrame.class
This is a generic messageFrame
class that extends frame. When you create an instance of this class,
you pass it a string that will be the title and then you pass it a string
that will be the message. This frame will automatically pack itself
to fit the size of the message. It also creates an Okay button. Below
is the part of the constructor that shows the way you should pass the title
and the message
Example:
public messageFrame(String title, String message){
When the user clicks on the Okay button, the frame hides and
disposes of itself.
Return to B2Client Documentation Contents
Return to B2 Documentation Contents
B2 Server Documentation
Contents
Introduction
Setting Pathnames
getDirectory() method
B2Server.class
Connection.class
LispListener.class
Introduction
This documentation describes the implementation of the server side of the B2
front-end software. There are three main classes in the server side
implementation.
An important method included in two of the classes is
getDirectory(). This method will be
discussed first and then each class.
In this implementation of a server, a lisp process is created for each
client and communication is accomplished through streams.
Setting Pathnames
You may set pathnames by making two changes in the B2Server class.
The lines occur early in the code and are marked by comments. The constant
defaults is used to dynamically allocated the scenario choice box. It sets
the default file which is to be read. The constant directory sets the pathname
where all the file are located. The lines which you must modify are the following:
String defaults = new String("C:\\InetPub\\wwwroot\\B2\\B2\\scenarioChoice.txt");
String directory = new String("C:\\InetPub\\wwwroot\\B2\\B2\\");
You will also need to make one change in the Connection class.
The code occurs in the startLisp() method. Since the server starts up and communicates
with a lisp process, you will need to change the directory of the lisp file which you
will be running. The line looks similar to the following:
lisppr = lisprt.exec("C:\\InetPub\\wwwroot\\B2\\B2\\b2-run.bat");
After you change the path name you must save and recompile B2Server.java.
getDirectory()
The getDirectory() method is responsible for setting the path names of all the
files that are used by the server. To use this method you just pass it the file
name and it attaches the directory to it. Currently, the code is set up to read the
directory String constant which you can change in the B2Server class and is
described in the section Setting Pathnames. Below is
the getDirectory() method that is used in the classes B2Server and Connection.
private String getDirectory(String file) {
// The line of code below is the path name that must be changed.
StringBuffer filepath = new StringBuffer(directory);
filepath.append(file);
return filepath.toString();
}
B2Server.class
The server is a thread that uses the ServerSocket class to listen to a port.
Once a connection is accepted, the server then creates a new socket object at
a different port which will communicate with the client at that new port. The
the ServerSocket will go back to listening for additional clients.
The B2Server constructor is responsible for creating the ServerSocket at
a given port. The thread is then started to allow the server to begin listening for
connections.
The main body of the server thread is the run() method. It loops forever,
listening for and accepting connections from clients. For each connection, the server
creates a connection object to handle communication through the new socket. The connection
object is passed the new socket and the server.
Connection.class
The connection class is the thread that handles all communication with the client. Like
the server, this class just listens at a given port for the client to do anything. Once
the client speaks this thread takes and processes that information by either handling it
itself to dynamically allocate the interface or sending it on for lisp to process.
The connection constructor is responsible for starting the thread and calling the
startLisp() method.
The startLisp() method opens the streams which communicate with the client and the streams
which communicate with lisp. It also is responsible for starting up the lisp process.
The method waits to open the stream, a print stream, which sends data to lisp until after it
has received the "*start*" token from lisp.
The other task belonging to startLisp() is to start the lisplistener thread. The
connection, data input stream from lisp, and the print stream to lisp are sent to the
lisplistener constructor.
The body of the connection class is the run() method. The run() method provides
the service to the client. Like the server class' run() method, the connection class' run
method continuously loops listening to a given port waiting for data from the client.
Once the run() method receives a message from the client in the form of
a string, it then processes that information. If the method reads the
tokens "*component*", "*stop*", or "*start*", then it calls the
appropriate method to handle the command. The token "*component*"
initalizes a call to the openBuildComponents method, "*stop*" causes a call to
the stopLisp() method, and "*start*" calls the startLisp() and openBuildComponents()
methods. Everything else is sent to lisp using the sendToLisp() method.
The sendToLisp method prints the line which is its parameter to the lisp process.
A new line character is also printed and then the stream is flushed.
The openBuildComponents() method sends the options for the choice interface.
It opens a file and for each line, reads the line and sends it to the client, until
the end of the file is reached.
The last method in the connection class is stopList(). It calls openBuildComponents()
to reload the default scenarios in the choice component of the interface. It stops the
lisplistener thread and kill the lisp process.
LispListener.class
The LispListener class is the thread which handles the data which lisp sends to the client.
Everything is sent to the client to handle, unless a token, "*selectscenario*" or "*default*",
is received. If one of the two possible tokens are received then openBuildComponents() in the
connection class is called.
Return to B2Server Documentation Contents
Return to B2 Documentation Contents