CS367 Programming Assignment 2
Lecture 3, Fall 2015
Due by 11:59 pm on Monday, October 19, 2015

Announcements

Check here periodically.

9/29/2015  Program assigned. To ask questions about the homework and see questions posed by other students and their answers, go to: https:piazza.com/wisc/fall2015/cs3673 and sign-in using your wisc.edu account.

Overview

Why are we doing this program?

Description

You probably have seen an LED display that loops through a sequence of messages (such as is depicted here). For this assignment you will implement a simple console-based editor that allows a user to create, edit, save, and load sequences of messages (which could then be uploaded into an LED-type display and shown in a continuous loop).

It is typical for today's programmers to use ADTs that are already implemented as part of a class library (e.g., C++ Standard Template Library) or an API (e.g., Java's Application Program Interface). Understanding ADT implementations is still important to be able to make informed choices as to which ADT implementation is best suited for an application in terms of memory and time efficiencies. For example, knowing the tradeoffs between array and linked implementations of the List ADT helps us choose between Java's ArrayList and LinkedList classes. It is also important to be able to implement your own data structures when pre-built ones are not available or when standard ADTs (and their operations) are unsuitable for the intended application.

In this assignment we provide you with an interface for a specialized ADT called a Loop. In addition to the main message loop editor application class, you will write a class which implements a Loop ADT using a circular doubly-linked list, as well as iterator and exception classes needed to support your Loop ADT implementation.

Goals

The goals of this assignment are to:

  • Understand and implement a circular, doubly-linked list.
  • Gain experience working with Java references (i.e., pointers).
  • Implement an iterator.
  • Implement an exception.
  • Gain experience writing classes which implement Java interfaces.
  • Develop an application that processes input commands.
  • Get more practice with command-line arguments and I/O.

Specifications

What are the program requirements?

The Loop ADT

A Loop is essentially a circular List. However, unlike a List, a Loop does not have a beginning or an end and items within the Loop cannot be accessed using a position. Instead, the Loop has a current item and the ability to move forward or backward. A Loop can be modified by removing the current item or by inserting an item before the current item. The Loop ADT is represented in Java by the Loop<E> interface which is provided for you (see Loop.java). Complete information about Loop operations can be found in the javadoc for the Loop<E> interface.

The LinkedLoop<E> Class

You will write a LinkedLoop<E> class (in a file named LinkedLoop.java) which implements the Loop<E> interface. In addition to the methods given in the Loop<E> interface, your LinkedLoop<E> class must have a constructor that takes no arguments and creates an empty loop. You may not add any other public constructors or methods.

The internal data structure used by your LinkedLoop<E> must be a circular, doubly-linked chain of nodes. You may not use Java's LinkedList class for this assignment. You must implement your own chain of doubly-linked nodes. To implement the circular, doubly-linked chain of nodes, you will need to use the DblListnode<E> class (provided for you; see DblListnode.java). Your LinkedLoop<E> class will have a field of type DblListnode<E> that references the node representing the current item. You may include other private fields that you find helpful, but no public fields.

Additional Related Classes

There are two other classes that you will need to write to go along with your LinkedLoop<E> class:

The EmptyLoopException class

The EmptyLoopException must be an unchecked exception. It is thrown by some methods (as described in the Loop<E> interface documentation).

The LinkedLoopIterator<E> class

The Loop<E> interface includes an iterator() method that returns an Iterator<E> object. You must write a specialized iterator class, named LinkedLoopIterator<E>, which will be used as the type of iterator returned by the LinkedLoop<E>'s iterator() method. The LinkedLoopIterator<E> class must implement the Iterator<E> interface (you do not need to implement the remove method - just throw an UnsupportedOperationException). You will need to write a constructor for your LinkedLoopIterator<E>; a package-access constructor that takes a DblListnode<E> as a parameter is suggested.

Remember that the purpose of an iterator is to provide a way to go through all the items in a collection exactly once. Make sure your LinkedLoopIterator is designed so that it starts with the current item and only goes through the items in the loop once.

Message Loop Editor Menu of Commands

The main method, in the file MessageLoopEditor.java, creates an empty Loop of messages and then prompts the user to enter commands, which it processes until the user types q for quit. The program prompts for input by displaying :

enter command (? for help): 

If a valid command is entered, your program should carry out the command.

The MessageLoopEditor.java file contains a partial implementation of the MessageLoopEditor class. Download this file and use it as the starting point for your MessageLoopEditor implementation.

Note that the provided MessageLoopEditor class is set up to do all necessary validation of input: if an invalid command is given the program displays "invalid command" and then displays the prompt again. (You may assume that at least one non-whitespace character will always be inputted.) The program also ensures the following:

  • For the a, b, f, u, s, and l commands, the program checks that the first character is followed by one or more spaces and the remainder of the line is a non-empty string starting with at least one non-whitespace character.
  • For the j command, the program checks that the first character is followed by one or more spaces and the remainder of the line is an integer.

You do not need to change any of the provided processing of input. What you do need to do is provide the implementations of the unimplemented commands.

Command format Description
? Display the following:
a (add after)  b (add before)  d (display)
f (find)       r (remove)      u (update) 
> (next)       < (previous)    j (jump)
s (save)       l (load)        q (quit)
This command has already been implemented for you.
a msg If the message loop is empty, add the new message to the loop and make it the current message. Otherwise, add the new message immediately after the current message and make the new message the new current message. In either case, display the current context (see note below).
b msg If the message loop is empty, add the new message to the loop and make it the current message. Otherwise, add the new message immediately before the current message and make the new message the new current message. In either case, display the current context (see note below).
d If the message loop is empty, display "no messages".  Otherwise, display all of the messages in the loop, starting with the current message, one message per line (going forward through the entire loop).
This command has already been implemented for you.
f string If the message loop is empty, display "no messages".  Otherwise, find (by searching forward in the message loop starting with the message after the current message) the first message that contains the given string.  If no message containing string is found, display "not found"; otherwise, make that message the current message and display the current context (see note below).
r If the message loop is empty, display "no messages". Otherwise, remove the current message from the message loop. If the message loop becomes empty as a result of the removal, display "no messages". Otherwise, make the message after the removed message the current message and display the current context (see note below).
u msg If the message loop is empty, display "no messages". Otherwise, update the current message by replacing it with the new message and display the current context (see note below).
> If the message loop is empty, display "no messages". Otherwise, go forward to the next message in the loop and display the current context (see note below).
< If the message loop is empty, display "no messages". Otherwise, go backward to the previous message in the loop and display the current context (see note below).
j N If the message loop is empty, display "no messages". Otherwise, jump N messages in the loop (forward if N > 0, backward if N < 0) and display the current context (see note below).
s filename If the message loop is empty, display "no messages to save". Otherwise, save all the messages to a file named filename, one message per line starting with the current message (and proceeding forward through the loop). If filename already exists, display "warning: file already exists, will be overwritten" before saving the messages. If filename cannot be written to, display "unable to save".
This command has already been implemented for you.
l filename (Note that this command is a lower-case L, not the number one.) If a file named filename does not exist or cannot be read from, display "unable to load". Otherwise, load the messages from filename in the order they are given before the current message. The current message is is not changed. You may assume that the input file contains one message per line, that there are no blank lines, and that the file is not empty (i.e., it has at least one line).
This command has already been implemented for you.
q Display "quit" and quit the program. This command has already been implemented for you.

Note: Displaying the current context means displaying the message immediately before the current message, the current message, and the message immediately after the current message (one per line). For example, if the current message is "No traffic delays", the message before current is "Rain expected later tonight", and the message after current is "Current outside temp: 83 F", your program should display:

     Rain expected later tonight
===[ No traffic delays ]===
     Current outside temp: 83 F

The "===[ ]===" are displayed to highlight the current message. However, if there are fewer than three messages in the loop, do the following:

  • If the loop contains only one message, such as "No traffic delays", then display:

    ===[ No traffic delays ]===
  • If the loop contains only two messages, such as "No traffic delays" and "Current outside temp: 83 F", then display showing the current message first:

    ===[ No traffic delays ]===
         Current outside temp: 83 F

Testing

Testing interactive programs can be frustrating if you aren't careful about recording the commands that you've entered. A bug can suddenly occur and you may not recall the exact sequence of commands to reproduce the bug. A technique for testing interactive programs is to process a fixed set of commands from an input file. Input files can be developed that test particular aspects of the program; these tests are easily repeated by running the program again on a particular input file.

The provided MessageLoopEditor has been written so that it can be provided with a single, optional, command-line argument that is the name of an input file containing message loop editor commands. If a command-line argument is not provided, then the program operates as an interactive console application reading commands from the console keyboard and displaying the results in the console window. If more than one command-line argument is given, the program displays "invalid command-line arguments" and quits.

If a single command-line argument is provided, it is assumed to be the name of an input file. If the file doesn't exist or is unable to be opened, the program displays "problem with input file" and quits. The program assumes the file contains lines that start with at least one non-whitespace character and that the last line always has a single "q" for quit.

How to proceed

After you have read this program page and given thought to the problem we suggest the following steps:

  1. Review these style and commenting standards that are used to evaluate your program's style.
  2. You may use the Java programming environment of your choice in CS 367. However, all programs must compile and run (using the Java 8 SE) for grading. We recommend that you use Eclipse. You may want to review the Eclipse tutorial to learn the basics.

  3. Download the provided files:

  4. Write the EmptyLoopException class.
  5. Incrementally implement and test the methods LinkedLoop class (leaving the iterator() method until the end). You might want to use a driver program for your tests.
  6. Implement and test the LinkedLoopIterator class and the iterator() method of the LinkedLoop class.

  7. Implement the MessageLoopEditor class, as described above, using a Loop object. Note: an implementation of the Loop ADT that uses an ArrayList internally is provided for you (in the file ArrayListLoop.java). You can use the ArrayListLoop as you develop and test your MessageLoopEditor class. This allows you to test your MessageLoopEditor independently from your LinkedLoop class and also means that you don't have to have your LinkedLoop class completely written and debugged before you start working on your MessageLoopEditor.
  8. Test your program by developing test files as described in the testing section above. Try this sample input file, sampleInput.txt and make sure your program produces the exact same output, sampleOutput.txt.

  9. Submit your work for grading.

Handing in

What should be handed in?

Make sure your code follows the style and commenting standards used in CS 302 and CS 367.

Electronically submit the following files to the Program 2 Dropbox on Learn@UW:

  • "LinkedLoop.java" containing your circular, doubly-linked circular loop class,
  • "EmptyLoopException.java" containing the unchecked exception used by the LinkedLoop class,
  • "LinkedLoopIterator.java" containing your LinkedLoop iterator class, and
  • "MessageLoopEditor.java" containing your message loop editor main program

Please turn in only the file named above. Extra files clutter up the Dropbox directories.

Last Updated: 8/21/2015     © 2015 Beck Hasti and Charles Fischer