SDSU CS 596 Java Programming
Fall Semester, 1998
Assignment 4 Solution
To Assignment Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 11-Dec-98

Contents of Doc D, Assignment 4 Solution



Listen Here!S-dec2 4mins Doc D, Assignment 4 Solution Slide # 2

Comments



Favor writing classes over writing programs

Send messages to object to get things done

Keep independent items independent

Do one thing at a time


Listen Here!S-dec2 1min Doc D, Assignment 4 Solution Slide # 3

Solution One

Overview


Building Blocks
LowerCaseInputStream
Converts input to lower case
UpperCaseInputStream
Converts input to upper case
NetworkInputStream (not used)
Opens an input stream on a socket


Listen Here!S-dec2 4mins Doc D, Assignment 4 Solution Slide # 4
NetworkInputStreamFuture
Opens an input stream on a socket. Does opening of socket in the background

NoCloseInputStream
Ignores the close method
NoCloseOutputStream
Ignores the close method
ReplacingInputStream
An input stream that uses regular expressions to modify input
ReplacingInputStreamFuture
An input stream that uses regular expressions to modify input. Regular expression is processed in background
ThreadEvent
ThreadListener
ThreadListenerHandler
System to handle exceptions in child threads

sdsu.util.ProgramProperties
Parses config file and command line
Program Classes
FilterMenus
Handles user interaction
FilterThread
Does the filtering of the input
FilterCreator
Creates FilterThreads, keeps FilterMenus and FilterThread separated

Listen Here!S-dec2 2mins Doc D, Assignment 4 Solution Slide # 5

LowerCaseInputStream

import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
class  LowerCaseInputStream extends FilterInputStream{
   public static final int EOF = -1;
   
   public LowerCaseInputStream( InputStream input )  {
      super( input );
   }
      
   public int read() throws IOException  {
      int nextChar = super.read();
      if ( nextChar == EOF )
         return EOF;
      else
         return Character.toLowerCase( (char) nextChar );
   }
   
   public int read(byte[] bytes, int offset, int length) throws IOException  {
      int charsRead = super.read(bytes, offset, length);
      
      if ( charsRead == EOF )
         return EOF;
         
      for ( int k = offset; k < offset + charsRead; k++)
         bytes[ k ] = (byte) Character.toLowerCase( (char)bytes[ k ] ) ;
      
      return charsRead;
   }
}

Doc D, Assignment 4 Solution Slide # 6

UpperCaseInputStream

import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
class  UpperCaseInputStream extends FilterInputStream {
   public static final int EOF = -1;
   
   public UpperCaseInputStream( InputStream input )  {
      super( input );
   }
      
   public int read() throws IOException  {
      int nextChar = super.read();
      if ( nextChar == EOF )
         return EOF;
      else
         return Character.toUpperCase( (char) nextChar );
   }
   
   public int read(byte[] bytes, int offset, int length) throws IOException  {
      int charsRead = super.read(bytes, offset, length);
      
      if ( charsRead == EOF )
         return EOF;
         
      for ( int k = offset; k < offset + charsRead; k++)
         bytes[ k ] = (byte) Character.toUpperCase( (char)bytes[ k ] ) ;
      
      return charsRead;
   }
}

Listen Here!S-dec2 3mins Doc D, Assignment 4 Solution Slide # 7

NoCloseInputStream & NoCloseOutputStream


import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
class  NoCloseInputStream extends FilterInputStream{
   
   public NoCloseInputStream( InputStream input ) {
      super( input );
   }
      
   public void close() {}   
}
import java.io.FilterOutputStream;
import java.io.OutputStream;
import java.io.IOException;
class  NoCloseOutputStream extends FilterOutputStream {
   
   public NoCloseOutputStream( OutputStream output ) {
      super( output );
   }
      
   public void close() {}   
}

Listen Here!S-dec2 54secs Doc D, Assignment 4 Solution Slide # 8

NetworkInputStream

import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
class  NetworkInputStream extends FilterInputStream{
   public static final int EOF = -1;
   
   public NetworkInputStream( int aPortNumber ) throws IOException{
      super( getSocketStream( aPortNumber ) );
   }
   private static InputStream getSocketStream( int aPortNumber ) 
      throws IOException{
      ServerSocket acceptor = new ServerSocket( aPortNumber );
      Socket client = acceptor.accept();
      return client.getInputStream();
   }
}

Listen Here!S-dec2 46secs, S-dec2 5mins Doc D, Assignment 4 Solution Slide # 9

NetworkInputStreamFuture

import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
import java.io.IOException;
public class NetworkInputStreamFuture extends InputStream{
   InputStream in;
   NetworkAcceptor dataServer;
   
   IOException networkIOException;
   
   public NetworkInputStreamFuture( int aPortNumber ) {
      dataServer = new NetworkAcceptor( aPortNumber);
      int runNowPriority = 
         Math.max( Thread.currentThread().getPriority() + 1, 
                     Thread.MAX_PRIORITY);
      dataServer.setPriority( runNowPriority );
      dataServer.start();
   }
      
   public int read() throws IOException {
      joinDataServer();   
      return in.read();
   }
   public int read(byte b[]) throws IOException {
      joinDataServer();   
      return read(b, 0, b.length);
   }
   public int read(byte b[], int off, int len) throws IOException {
      joinDataServer();   
      return in.read(b, off, len);
   }

Doc D, Assignment 4 Solution Slide # 10
NetworkInputStreamFuture Continued
   public long skip(long n) throws IOException {
      joinDataServer();   
      return in.skip(n);
   }
   public int available() throws IOException  {
      joinDataServer();   
      return in.available();
   }
   public void close() throws IOException {
      joinDataServer();   
      in.close();
   }
   public synchronized void mark(int readlimit){}
   public synchronized void reset() throws IOException {
      joinDataServer();   
      in.reset();
   }
   
   public boolean markSupported() {
      return false;
   }
   

Listen Here!S-dec2 2mins Doc D, Assignment 4 Solution Slide # 11
NetworkInputStreamFuture Continued

   private void joinDataServer() throws IOException{
      try {
         dataServer.join();
      }
      catch (InterruptedException threadError ){
         throw new IOException( "Network Acceptor interrupted while awaiting");
      }
      if (networkIOException != null )
         throw networkIOException;
   }
      
   class NetworkAcceptor extends Thread {
      int portNumber;
      
      public NetworkAcceptor( int aPortNumber ){
         portNumber = aPortNumber;
      }
         
      public void run() {
         try {
            ServerSocket acceptor = new ServerSocket( portNumber );
            Socket client = acceptor.accept();
            in = client.getInputStream();
         }
         catch (IOException socketIOException ) {
            networkIOException = socketIOException;
         }
      }
   }
}

Listen Here!S-dec2 5mins Doc D, Assignment 4 Solution Slide # 12

ReplacingInputStream

import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.StringBufferInputStream;
import java.io.IOException;
import gnu.regexp.REException;
import gnu.regexp.RE;
import gnu.regexp.RESyntax;
import gnu.regexp.REMatch;
class ReplacingInputStream extends FilterInputStream
   {   
   public ReplacingInputStream( InputStream in, 
                              String pattern, 
                              String replacement ) throws IOException, REException {
      super( getREStream( in, pattern, replacement ) );
   }
   private static InputStream getREStream( InputStream in, 
                              String pattern, 
                              String replacement ) throws IOException, REException {
      RE replacer = new RE( pattern );
      String result = replacer.substituteAll( in, replacement );
      return new  StringBufferInputStream( result );
   }
}

Doc D, Assignment 4 Solution Slide # 13

ReplacingInputStreamFuture

import java.io.InputStream;
import java.io.IOException;
import gnu.regexp.REException;
public class ReplacingInputStreamFuture extends InputStream {
   InputStream in;
   REReplacer inputServer;
   
   IOException futureException;
   
   public ReplacingInputStreamFuture( InputStream in, 
                                       String pattern, 
                                       String replacement  ) {
      inputServer = new REReplacer( in, pattern, replacement );
      inputServer.start();
   }
      
   public int read() throws IOException {
      joinREReplacer();   
      return in.read();
   }
   public int read(byte b[]) throws IOException {
      joinREReplacer();   
      return read(b, 0, b.length);
   }
   public int read(byte b[], int off, int len) throws IOException {
      joinREReplacer();   
      return in.read(b, off, len);
   }

Doc D, Assignment 4 Solution Slide # 14
ReplacingInputStreamFuture Continued
   public long skip(long n) throws IOException  {
      joinREReplacer();   
      return in.skip(n);
   }
   public int available() throws IOException  {
      joinREReplacer();   
      return in.available();
   }
   public void close() throws IOException {
      joinREReplacer();   
      in.close();
   }
   public synchronized void mark(int readlimit){ }
   public synchronized void reset() throws IOException  {
      joinREReplacer();   
      in.reset();
   }
   
   public boolean markSupported() { return false; }
   
   private void joinREReplacer() throws IOException {
      try {
         inputServer.join();
      }
      catch (InterruptedException threadError ) {
         throw new IOException( "RE Replacer Thread interrupted");
      }
      if (futureException != null )
         throw futureException;
   }

Doc D, Assignment 4 Solution Slide # 15
ReplacingInputStreamFuture Continued
      
   class REReplacer extends Thread {
      private InputStream originalIn;
      String pattern;
      String replacement;
             
      public REReplacer(InputStream in, 
                              String aPattern, 
                              String aReplacement  ) {
         originalIn = in;
         pattern = aPattern;
         replacement = aReplacement;
      }
      public void run() {
         try {
            in =  new ReplacingInputStream( originalIn, pattern, replacement );
         }
         catch (IOException aStartException ) {
            futureException = aStartException;
         }
         catch (REException reProblem ) {
            futureException = new IOException( "REException occured:" + 
               reProblem.toString() );
         }
      }
   }
}

Doc D, Assignment 4 Solution Slide # 16

ThreadEvent

import java.util.EventObject;
public class ThreadEvent extends EventObject {
   Exception thrown;
   Object result;
   String message;
   
   public ThreadEvent( Object source ) { super( source ); }
   
   public ThreadEvent( Object source, Object threadResult ) {
      super( source );
      result = threadResult;
   }
   public ThreadEvent( Object source, Exception threadException ) {
      super( source );
      thrown = threadException;
   }
   
   public Exception getException() { return thrown; }
   
   public Object getResult() { return result; }
   public void setMessage( String aMessage ) { message = aMessage; }
   
   public String getMessage() { return message; }
}
public interface ThreadListener {
   public void threadResult( ThreadEvent anEvent );
   public void threadExceptionThrown( ThreadEvent anEvent );
}

Doc D, Assignment 4 Solution Slide # 17

ThreadListenerHandler


import java.util.*;
public class ThreadListenerHandler {
   ArrayList listeners = new ArrayList();
   Object theListened; 
   
   public ThreadListenerHandler( Object listened ) {
      theListened = listened;
   }
   
   public synchronized void  addThreadListener( ThreadListener aListener ) {
      listeners.add( aListener );
   }
   public synchronized void  removeThreadListener( ThreadListener aListener ) {
      listeners.remove( aListener );
   }
   public void broadcastResult( ThreadEvent anEvent ) {
      Iterator sendList;
      synchronized ( this ) {
         sendList = ( (ArrayList ) listeners.clone()).iterator();
      }
      
      while ( sendList.hasNext() ) {
         ThreadListener aListener = (ThreadListener) sendList.next();
         aListener.threadResult( anEvent );
      }
   }

Doc D, Assignment 4 Solution Slide # 18
ThreadListenerHandler Continued

   public void broadcastResult( Object result ) {
      
      ThreadEvent broadcastData = 
         new ThreadEvent( theListened, result );
      broadcastResult(    broadcastData );
   }
   public void broadcastException( Exception anException ) {
      ThreadEvent broadcastData = 
         new ThreadEvent( theListened, anException );
      broadcastException(    broadcastData );
   }
   public void broadcastException( ThreadEvent anEvent ) {
      Iterator sendList;
      synchronized ( this ) {
         sendList = ( (ArrayList ) listeners.clone()).iterator();
      }
      
      while ( sendList.hasNext() ) {
         ThreadListener aListener = (ThreadListener) sendList.next();
         aListener.threadExceptionThrown( anEvent );
      }
   }
}

Listen Here!S-dec2 1min Doc D, Assignment 4 Solution Slide # 19

FilterThread

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
 * Note the order of methods called is important. Must first set
 * input source and output destination. Second must make call to 
 * uncompressInput() if it is needed. 
 */
class FilterThread extends Thread{
   public static final int INTERACTIVE_PRIORITY = 5;
   public static final int BACKGROUND_PRIORITY = 4;
   
   ThreadListenerHandler listeners = new ThreadListenerHandler( this);
   InputStream in;
   OutputStream out;
   
   //Used in error reporting, identifies thread's settings
   String inputSource = "not set";
   String outputDestination = "not set";
   String filters = "";
   
   public FilterThread(  ){
      setPriority( BACKGROUND_PRIORITY );
   }

Listen Here!S-dec2 2mins Doc D, Assignment 4 Solution Slide # 20
FilterThread Continued
   public void keyboardInput(){
      in = new NoCloseInputStream( System.in );
      setPriority( INTERACTIVE_PRIORITY );
      inputSource = "keyboard";
   }
   public void fileInput( String fileName ) throws IOException {
      inputSource = "file: " + fileName;
      File inputFile = new File( fileName );
      if ( !inputFile.exists() ) {
         throw new IOException( "Input file: " + fileName + 
            " does not exist" );
      }
      in = new BufferedInputStream( 
               new FileInputStream( inputFile ));
   }
   public void networkInput( int socketNumber ) throws IOException {
      inputSource = "network socket: " + socketNumber;
      in = new BufferedInputStream( 
               new NetworkInputStreamFuture( socketNumber ));
   }
   public void screenOutput() {
      outputDestination = "screen";
      out = new NoCloseOutputStream( System.out );
      setPriority( INTERACTIVE_PRIORITY );
   }

Doc D, Assignment 4 Solution Slide # 21
FilterThread Continued
   public void fileOutput( String fileName ) throws IOException {
      SimpleDateFormat formatter = 
         new SimpleDateFormat( ".yy-DDD-HH:mm:ss");
      Date now = new Date();
      String timeStamp = formatter.format( now );
      
      fileName = fileName + timeStamp;
      outputDestination = "file: " + fileName;
      out = new BufferedOutputStream( 
               new FileOutputStream( fileName ));
   }
   public void uncompressInput()  throws IOException {
      filters = filters + " compressed input";
      in = new GZIPInputStream( in );
   }
   public void upperCaseText()  throws IOException {
      filters = filters + " Upper case";
      in = new UpperCaseInputStream( in );
   }
   public void lowerCaseText()  throws IOException {
      filters = filters + " Upper case";
      in = new LowerCaseInputStream( in );
   }
   public void compressOutput()  throws IOException {
      filters = filters + " compressed output";
      out = new GZIPOutputStream( out );
   }

Listen Here!S-dec2 3mins Doc D, Assignment 4 Solution Slide # 22
FilterThread Continued
   public void replaceText( String pattern, String replacement ) {
      filters = filters + " replace: " + pattern + " with: " + replacement;
      in = new ReplacingInputStreamFuture( in, pattern, replacement );
   }
   public synchronized void  addThreadListener( ThreadListener aListener )  {
      listeners.addThreadListener( aListener );
   }
   public synchronized void  removeThreadListener( ThreadListener aListener ) {
      listeners.removeThreadListener( aListener );
   }
   public void run() {
      final int  EOF = -1;
      final int  bufferSize = 1024;
      
      int charsRead = 0;
      byte[] buffer = new byte[ bufferSize];
      
      try {
         charsRead = in.read( buffer, 0, bufferSize);
         while ( charsRead != EOF ) {
            out.write(  buffer, 0, charsRead );
            charsRead = in.read( buffer, 0, bufferSize);
         }
      }
      catch (Exception ioProblem ) {
         broadcastException( ioProblem );
      }
      finally  { closeStreams(); }
   }
   

Doc D, Assignment 4 Solution Slide # 23
FilterThread Continued
   private void closeStreams() {
      try {
         in.close();
         out.close();
      }
      catch (IOException closeProblem ) {
         listeners.broadcastException( closeProblem );
      }
   }
         
   public void broadcastException( Exception problem ) {
      ThreadEvent exceptionInfo = new ThreadEvent( this, problem );
      String lineSeparator = System.getProperty( "line.separator" );
      String message = "Input: " + inputSource + lineSeparator +
         "output: " + outputDestination + lineSeparator + 
         "filters: " + filters;
   
      exceptionInfo.setMessage( message );
      listeners.broadcastException( exceptionInfo );
   }
}

Listen Here!S-dec2 2mins Doc D, Assignment 4 Solution Slide # 24

FilterCreator

import sdsu.util.ProgramProperties;
import java.io.*;
import java.text.*;
import java.util.*;
public class FilterCreator{
   ProgramProperties ioOptions;
   
   public FilterCreator( ProgramProperties options ) {
      ioOptions = options;
   }
   public static void main( String[] args ) throws IOException {
      FilterCreator main = 
         new FilterCreator( new ProgramProperties( args, "config.properties" ) );
      FilterMenus userInput = new FilterMenus( System.in, System.out, main );
      userInput.run();
   }
   
   public void processFileInput( String fileName, ThreadListener errorReporter ){
      FilterThread fileProcessor = new FilterThread();
      try {
         fileProcessor.fileInput( fileName );
         addFilters( fileProcessor );
         fileProcessor.addThreadListener(errorReporter);
         fileProcessor.start();
         joinOnScreenOutput( fileProcessor );
      }
      catch (Exception error ) {
         errorReporter.threadExceptionThrown( new ThreadEvent( this, error ) );
      }
   }

Doc D, Assignment 4 Solution Slide # 25
FilterCreator Continued

   public void processNetworkInput( int portNumber, 
                                    ThreadListener errorReporter) {
      FilterThread networkProcessor = new FilterThread();
      try {
         networkProcessor.networkInput( portNumber );
         addFilters( networkProcessor );
         networkProcessor.addThreadListener(errorReporter);
         networkProcessor.start();
         joinOnScreenOutput( networkProcessor );
      }
      catch (Exception error ) {
         errorReporter.threadExceptionThrown( new ThreadEvent( this, error ) );
      }
   }
   
   public void processKeyboardInput( ThreadListener errorReporter  ) 
      throws IOException {
      FilterThread keyboardProcessor = new FilterThread();
      try {
         keyboardProcessor.keyboardInput();
         addFilters( keyboardProcessor );
         keyboardProcessor.addThreadListener(errorReporter);
         keyboardProcessor.start();
         keyboardProcessor.join();
      }
      catch (Exception error ) {
         errorReporter.threadExceptionThrown( new ThreadEvent( this, error ) );
      }
   }

Doc D, Assignment 4 Solution Slide # 26
FilterCreator Continued
   void addFilters( FilterThread aFilterThread ) throws IOException {
      //Order is important
      addOutput( aFilterThread );
      addCompression( aFilterThread );
      addReplacement( aFilterThread );
      addCaseFilter( aFilterThread );
   }
   void addReplacement( FilterThread aFilterThread ) throws IOException {
      if ( ! ioOptions.containsKey( "pattern") )
         return;
      if ( ! ioOptions.containsKey( "replacement") )
         return;
      String pattern = ioOptions.getString( "pattern" );
      String replacement = ioOptions.getString( "replacement" );
      aFilterThread.replaceText( pattern, replacement );
   }
   
   void addOutput( FilterThread aFilterThread ) throws IOException {
      String output = ioOptions.getString( "output", "screen" );
      if ( output.equals( "file" ) ) {
         String fileName =  ioOptions.getString( "outputFile" );
         aFilterThread.fileOutput( fileName );
      }
      else if ( output.equals( "screen" ))
         aFilterThread.screenOutput();
      else
         throw new IOException( "Invalid output device: " + output );
   }

Doc D, Assignment 4 Solution Slide # 27
FilterCreator Continued
   void addCompression( FilterThread aFilterThread ) throws IOException {
      String inCompression = ioOptions.getString( "compressedInput", "false" );
      if ( inCompression.equals( "true" ) )
         aFilterThread.uncompressInput(  );
      String outCompression = 
         ioOptions.getString( "compressedOutput", "false" );
      if ( outCompression.equals( "true" ) )
         aFilterThread.compressOutput(  );
   }
   void addCaseFilter( FilterThread aFilterThread ) throws IOException {
      String textCase = ioOptions.getString( "textCase", "noChange" ).trim();
      if ( textCase.equals( "upper" ) )
         aFilterThread.upperCaseText(  );
      else if ( textCase.equals( "lower" ) )
         aFilterThread.lowerCaseText(  );
   }
   private void joinOnScreenOutput( FilterThread aFilter ) 
      throws InterruptedException {
      String output = ioOptions.getString( "output", "screen" );
      if ( output.equals( "screen" ) )
         aFilter.join();
   }
}

Listen Here!S-dec2 3mins Doc D, Assignment 4 Solution Slide # 28

FilterMenus

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.PrintStream;
import sdsu.io.ASCIIInputStream;
import java.util.*;
class FilterMenus implements ThreadListener {
   static final String FILE = "1";
   static final String NETWORK = "2";
   static final String KEYBOARD = "3";
   static final String QUIT = "q";
   static final String SEPARATOR = "----";
   
   ASCIIInputStream in;
   PrintStream out;
   FilterCreator processor;
   ArrayList errorMessages = new ArrayList();
   
   public FilterMenus( InputStream anInput, 
                        OutputStream anOutput, 
                        FilterCreator aProcessor ) {
      in = new ASCIIInputStream( anInput);
      out = new PrintStream( anOutput);
      processor = aProcessor;
   }
   // No results are sent back, only exceptions
   public void threadResult( ThreadEvent anEvent ) { }
      
   public void threadExceptionThrown( ThreadEvent anEvent ){
      synchronized ( errorMessages ) { errorMessages.add( anEvent ); }
   }

Listen Here!S-dec2 1min Doc D, Assignment 4 Solution Slide # 29
FilterMenus Continued
   public void run() {
      String selection;
      try {
         do  {
            displayErrorMessages();
            selection = getMainMenusResult();
            handleUserSelection( selection );
         }
         while ( !selection.equals( QUIT ) );
         displayErrorMessages();
         out.println( "Good Bye" );
      }
      catch ( IOException readWriteProblem ){
         System.err.println( "There was a problem interacting with the user" );
      }
   }
   void displayErrorMessages() {
      Iterator toDisplay;
      synchronized ( errorMessages )  {
         toDisplay = ( (ArrayList ) errorMessages.clone()).iterator();
         errorMessages.clear();
      }
      while ( toDisplay.hasNext() ) {
         ThreadEvent anEvent = (ThreadEvent) toDisplay.next();
         out.println( SEPARATOR );
         out.println( "There was a problem with your request");
         out.println( anEvent.getMessage() );
         out.println( anEvent.getException() );
      }
   }

Listen Here!S-dec2 10mins Doc D, Assignment 4 Solution Slide # 30
FilterMenus Continued
   String getMainMenusResult() throws IOException {
      String selection = showMainMenus();
      while ( !validateMainMenusInput( selection ) ) {
         out.println( selection + " not valid input, try again.");
         selection = showMainMenus();
      }
      return  selection.trim().toLowerCase();
   }
   String showMainMenus() throws IOException {
      out.println( SEPARATOR);
      out.println( "Select one of the following:");
      out.println( "   1. File input");
      out.println( "   2. Network input");
      out.println( "   3. Keyboard input");
      out.println( "   Q. Quit");
      out.print( "Type your selection: ");
      String input = in.readLine();
      return input;
   }
   boolean validateMainMenusInput( String input ) {
      if (input == null )  return false;
         
      input = input.trim().toLowerCase();
      
      if (input.length() == 0 ) return false;
      
      if (input.startsWith( FILE )  || input.startsWith( NETWORK ) || 
         input.startsWith( KEYBOARD ) || input.startsWith( QUIT ) )
         return true;
      
      return false;
   }

Doc D, Assignment 4 Solution Slide # 31
FilterMenus Continued
   void handleUserSelection( String selection ) throws IOException {
      if (selection.startsWith( FILE ) ) {
         String fileName = getFileName();
         processor.processFileInput( fileName, this );
      }
      else if (selection.startsWith( NETWORK ) ) {
         int socketNumber = getSocket();
         processor.processNetworkInput( socketNumber, this );
      }
      else if (selection.startsWith( KEYBOARD ) )
         processor.processKeyboardInput( this );
   }
      
   
   int getSocket( ) throws IOException {
      out.println( SEPARATOR);
      out.print( "Type the socket number: ");
      int input = in.readInt();
      in.flushLine();
      
      while ( input < 5000 ) {
         out.println( "" + input +  
               " is not a valid socket number between 5000 and 65536. Try again. ");
         out.println( SEPARATOR);
         out.print( "Type the socket number: ");
         input =  in.readInt();
         in.flushLine();
      }
      return input;
   } 

Doc D, Assignment 4 Solution Slide # 32
FilterMenus Continued

   String getFileName( ) throws IOException {
      out.println( SEPARATOR);
      out.print( "Type the name of the file: ");
      String input = in.readLine();
      
      while ( input == null || input.length() == 0 ) {
         out.println( "Not a valid file name. Try again. " );
         out.println( SEPARATOR);
         out.print( "Type the name of the file: ");
         input = in.readLine();
      }
      return input;
   } 
}

Doc D, Assignment 4 Solution Slide # 33

Improvements


Use a counting semaphore to synchronize keyboard & screen use. This will provide better concurrency than using the joins.

Use reflection to remove the order dependencies of the method calls in FilterThread.

Create a prototype FilterThread with the settings from the config file and command line.

The above three improvements should allow us to remove the class FilterCreator

Create a generic ASCI Menu system to replace FilterMenu
Copyright © 1998 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
All rights reserved.

visitors since 07-Dec-98