×

Welcome to TagMyCode

Please login or create account to add a snippet.
0
0
 
0
Language: Java
Posted by: Moussa abuwalid
Added: Apr 30, 2021 1:40 AM
Views: 3963
Tags: no tags
  1.  
  2. import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
  3. import java.io.BufferedReader;
  4. import java.io.IOException;
  5. import java.io.InputStreamReader;
  6. import java.util.Arrays;
  7. import java.util.LinkedList;
  8. import java.util.List;
  9. import java.util.stream.Collectors;
  10. import sep.tinee.net.message.Bye;
  11. import sep.tinee.net.message.Push;
  12. import sep.tinee.net.message.ReadReply;
  13. import sep.tinee.net.message.ReadRequest;
  14.  
  15. /**
  16.  * This class is an initial work-in-progress prototype for a command line
  17.  * Tinee client. It has been hastily hacked together, as often the case
  18.  * in early exploratory coding, and is incomplete and buggy. However, it
  19.  * does compile and run, and <i>some</i> basic functionality, such as pushing
  20.  * and reading tines to and from an instance of
  21.  * {@link sep.tinee.server.Server}, is working. Try it out!
  22.  * <p>
  23.  * The arguments required to run a client correspond to the
  24.  * {@link #set(String, String, int)} method: a user name, and the host name
  25.  * and port number of a Tinee server.
  26.  * <p>
  27.  * You can compile and run this client using <b>NetBeans</b>; e.g., right-click
  28.  * this file in the NetBeans editor and select "Run File".  Note, to provide
  29.  * the above arguments, you should set up a <b>run configuration</b> for this
  30.  * class: {@literal ->} "Set Project Configuration" {@literal ->} "Customize..."
  31.  * {@literal ->} "New...".
  32.  * <p>
  33.  * Assuming compilation using NetBeans (etc.), you can also run {@code Client}
  34.  * from the command line; e.g., on Windows, run:
  35.  * <ul>
  36.  * <li style="list-style-type: none;">
  37.  * {@code C:\...\tinee>  java -cp build\classes Client userid localhost 8888}
  38.  * </ul>
  39.  * <p>
  40.  * You will be significantly reworking and extending this client: your aim is
  41.  * to meet the specification, and you have mostly free rein to do so.
  42.  * (That is as opposed to the base framework, which you are <b>not</b> permitted
  43.  * to modify, i.e., the packages {@link sep.tinee.server},
  44.  * {@link sep.tinee.server}, {@link sep.tinee.server} and]
  45.  * {@link sep.tinee.server}.) The constraints on your client are:
  46.  * <ul>
  47.  * <li>
  48.  * You must retain a class named {@code Client}) as the frontend class for
  49.  * running your client, i.e., via its static {@linkplain #main(String[]) main}
  50.  * method.
  51.  * <li>
  52.  * The {@linkplain Client#main(String[]) main} method must accept the <i>same
  53.  * arguments</i> as currently, i.e., user name, host name and port number.
  54.  * <li>
  55.  * Your client must continue to accept user commands on the <i>standard input
  56.  * stream</i> ({@code System.in}), and output on the <i>standard output
  57.  * stream</i> ({@code System.out}).
  58.  * <li>
  59.  * Any other conditions specified by the assignment tasks.
  60.  * </ul>
  61.  * <p>
  62.  * <i>Tip:</i> generate and read the <b>JavaDoc</b> API documentation for the
  63.  * provided base framework classes (if you're not already reading this there!).
  64.  * After importing the code project into NetBeans, right-click the project in
  65.  * the "Projects" window and select "Generate Javadoc".
  66.  * By default, the output is written to the {@code dist/javadoc} directory.
  67.  * You can directly read the comments in the code for the same information, but
  68.  * the generated JavaDoc is formatted more nicely as HTML with click-able links.  
  69.  *
  70.  * @see CLFormatter
  71.  */
  72. public class Client {
  73.  
  74.   String user;
  75.   String host;
  76.   int port;
  77.  
  78.   boolean printSplash = true;
  79.  
  80.   Client() {
  81.   }
  82.  
  83.   public static void main(String[] args) throws IOException {
  84.     String user = args[0];
  85.     String host = args[1];
  86.     int port = Integer.parseInt(args[2]);
  87.     Client client = new Client();
  88.     client.set(user, host, port);
  89.     client.run();
  90.   }
  91.  
  92.   public void set(String user, String host, int port) {
  93.     this.user = user;
  94.     this.host = host;
  95.     this.port = port;
  96.   }
  97.  
  98.   // Run the client
  99.   @SuppressFBWarnings(
  100.       value = "DM_DEFAULT_ENCODING",
  101.       justification = "When reading console, ignore 'default encoding' warning")
  102.   void run() throws IOException {
  103.  
  104.     BufferedReader reader = null;
  105.     CLFormatter helper = null;
  106.     try {
  107.       reader = new BufferedReader(new InputStreamReader(System.in));
  108.  
  109.       if (this.user.isEmpty() || this.host.isEmpty()) {
  110.         System.err.println("User/host has not been set.");
  111.         System.exit(1);
  112.       }
  113.       helper = new CLFormatter(this.host, this.port);
  114.  
  115.       if (this.printSplash = true);
  116.       {
  117.         System.out.print(helper.formatSplash(this.user));
  118.       }
  119.       loop(helper, reader);
  120.     } catch (Exception ex) {
  121.       throw new RuntimeException(ex);
  122.     } finally {
  123.       reader.close();
  124.       if (helper.chan.isOpen()) {
  125.         // If the channel is open, send Bye and close
  126.         helper.chan.send(new Bye());
  127.         helper.chan.close();
  128.       }
  129.     }
  130.   }
  131.  
  132. // Main loop: print user options, read user input and process
  133.   void loop(CLFormatter helper, BufferedReader reader) throws IOException,
  134.  
  135.     // The app is in one of two states: "Main" or "Drafting"
  136.     String state = "Main";  // Initial state
  137.  
  138.     // Holds the current draft data when in the "Drafting" state
  139.     String draftTag = null;
  140.     List<String> draftLines = new LinkedList<>();
  141.  
  142.     // The loop
  143.     for (boolean done = false; !done;) {
  144.  
  145.       // Print user options
  146.       if (state.equals("Main")) {
  147.         System.out.print(helper.formatMainMenuPrompt());
  148.       } else {  // state = "Drafting"
  149.         System.out.print(helper.
  150.             formatDraftingMenuPrompt(draftTag, draftLines));
  151.       }
  152.  
  153.       // Read a line of user input
  154.       String raw = reader.readLine();
  155.       if (raw == null) {
  156.         throw new IOException("Input stream closed while reading.");
  157.       }
  158.       // Trim leading/trailing white space, and split words according to spaces
  159.       List<String> split = Arrays.stream(raw.trim().split("\\ "))
  160.           .map(x -> x.trim()).collect(Collectors.toList());
  161.       String cmd = split.remove(0);  // First word is the command keyword
  162.       String[] rawArgs = split.toArray(new String[split.size()]);
  163.       // Remainder, if any, are arguments
  164.  
  165.       // Process user input
  166.       if ("exit".startsWith(cmd)) {
  167.         // exit command applies in either state
  168.         done = true;
  169.       } // "Main" state commands
  170.       else if (state.equals("Main")) {
  171.         if ("manage".startsWith(cmd)) {
  172.           // Switch to "Drafting" state and start a new "draft"
  173.           state = "Drafting";
  174.           draftTag = rawArgs[0];
  175.         } else if ("read".startsWith(cmd)) {
  176.           // Read tines on server
  177.           helper.chan.send(new ReadRequest(rawArgs[0]));
  178.           ReadReply rep = (ReadReply) helper.chan.receive();
  179.           System.out.print(
  180.               helper.formatRead(rawArgs[0], rep.users, rep.lines));
  181.         } else {
  182.           System.out.println("Could not parse command/args.");
  183.         }
  184.       } // "Drafting" state commands
  185.       else if (state.equals("Drafting")) {
  186.         if ("line".startsWith(cmd)) {
  187.           // Add a tine message line
  188.           String line = Arrays.stream(rawArgs).
  189.               collect(Collectors.joining());
  190.           draftLines.add(line);
  191.         } else if ("push".startsWith(cmd)) {
  192.           // Send drafted tines to the server, and go back to "Main" state
  193.           helper.chan.send(new Push(user, draftTag, draftLines));
  194.           state = "Main";
  195.           draftTag = null;
  196.         } else {
  197.           System.out.println("Could not parse command/args.");
  198.         }
  199.       } else {
  200.         System.out.println("Could not parse command/args.");
  201.       }
  202.     }
  203.     return;
  204.   }
  205. }
  206.