From c3a28e6849972d1bbca2a507006d0c3c9e466aca Mon Sep 17 00:00:00 2001
From: Christopher Bohn <bohn@unl.edu>
Date: Tue, 4 Feb 2020 11:49:13 -0600
Subject: [PATCH] Refactored for improved testability

---
 .../edu/unl/cse/csce361/socket_chat/Chat.java | 70 ++++++++++++-------
 1 file changed, 45 insertions(+), 25 deletions(-)

diff --git a/src/main/java/edu/unl/cse/csce361/socket_chat/Chat.java b/src/main/java/edu/unl/cse/csce361/socket_chat/Chat.java
index cffcb5b..78fceee 100644
--- a/src/main/java/edu/unl/cse/csce361/socket_chat/Chat.java
+++ b/src/main/java/edu/unl/cse/csce361/socket_chat/Chat.java
@@ -273,40 +273,58 @@ public class Chat {
                              PrintStream remoteOutput) {
         // "Connection established. Host goes first."
         System.out.println(bundle.getString("connection.info.ready"));
-        String message = "";
         boolean keepTalking = true;
         boolean myTurnToTalk = isHost;
+        while (keepTalking) {
+            keepTalking = communicateOneMessage(localInput, remoteInput, localOutput, remoteOutput, myTurnToTalk);
+            myTurnToTalk = !myTurnToTalk;
+        }
+    }
+
+    /**
+     * Processes a single message from one chatter to the other.
+     *
+     * @param localInput   a {@link java.io.BufferedReader} that gets user input from this end of the connection
+     * @param remoteInput  a {@link java.io.BufferedReader} that gets user input from the other end of the connection
+     * @param localOutput  a {@link java.io.PrintStream} that outputs to the user at this end of the connection
+     * @param remoteOutput a {@link java.io.PrintStream} that outputs to the user at the other end of the connection
+     * @param localMessage {@code true} if the message to be processed will originate locally, {@code false} if remotely
+     * @return {@code true} if the program should continue to execute after processing the message; {@code false}
+     * otherwise
+     */
+    boolean communicateOneMessage(BufferedReader localInput, BufferedReader remoteInput,
+                                  PrintStream localOutput, PrintStream remoteOutput, boolean localMessage) {
+        String message = "";
+        boolean keepTalking = true;
         try {
-            while (keepTalking) {
-                try {
-                    if (myTurnToTalk) {
-                        message = localInput.readLine();
-                        remoteOutput.println(encipher(message));
+            try {
+                if (localMessage) {
+                    message = localInput.readLine();
+                    remoteOutput.println(encipher(message));
+                } else {
+                    String encipheredMessage = remoteInput.readLine();
+                    if (encipheredMessage != null) {
+                        message = decipher(encipheredMessage);
+                        localOutput.println(message);
                     } else {
-                        String encipheredMessage = remoteInput.readLine();
-                        if (encipheredMessage != null) {
-                            message = decipher(encipheredMessage);
-                            localOutput.println(message);
-                        } else {
-                            // "Received null message: lost connection to remote chatter. Terminating."
-                            localOutput.println(bundle.getString("communicate.error.nullMessageFromRemote"));
-                            keepTalking = false;
-                        }
+                        // "Received null message: lost connection to remote chatter. Terminating."
+                        localOutput.println(bundle.getString("communicate.error.nullMessageFromRemote"));
+                        keepTalking = false;
                     }
-                } catch (SocketException ignored) {
-                    // "Unable to exchange message: lost connection to remote chatter. Terminating."
-                    localOutput.println(bundle.getString("communicate.error.cannotSendMessage"));
-                    keepTalking = false;
                 }
-                if (keepTalking && keywords.contains(message)) {
-                    keepTalking = handleKeyword(message, myTurnToTalk, localInput, localOutput);
-                }
-                myTurnToTalk = !myTurnToTalk;
+            } catch (SocketException ignored) {
+                // "Unable to exchange message: lost connection to remote chatter. Terminating."
+                localOutput.println(bundle.getString("communicate.error.cannotSendMessage"));
+                keepTalking = false;
+            }
+            if (keepTalking && keywords.contains(message)) {
+                keepTalking = handleKeyword(message, localMessage, localInput, localOutput);
             }
         } catch (IOException ioException) {
             System.err.println("Connection dropped: " + ioException);
             System.exit(1);
         }
+        return keepTalking;
     }
 
     /**
@@ -319,11 +337,13 @@ public class Chat {
      * @param output       a {@link java.io.PrintStream} for output to the user
      * @return {@code true} if the program should continue to execute after processing the keyword; {@code false}
      * otherwise
+     * @throws IOException if an I/O error occurs while reading user responses to prompts
      */
-    private boolean handleKeyword(String keyword, boolean localMessage, BufferedReader input, PrintStream output) {
+    boolean handleKeyword(String keyword, boolean localMessage, BufferedReader input, PrintStream output)
+            throws IOException {
         if (keyword.equals(bundle.getString("communicate.keyword.exit"))) {
             return false;
-        // Un-comment this next code block in step 3 of the assignment.
+            // Un-comment this next code block in step 3 of the assignment.
         /*
         } else if (keyword.equals(bundle.getString("communicate.keyword.setLocale"))) {
             if (localMessage) {
-- 
GitLab