Lab 5 Exceptions Exceptions indicate that a program has encountered an unforeseen problem. While some problems place programmers at fault (for example, using an index that is outside the boundaries of an array) others are unpredictable (for example, a file cannot be saved because the hard drive crashed). Programming languages are now designed to throw exceptions when these problems happen. In some cases, catching exceptions allows users a choice of alternative courses of action (for example, the user can select another drive to save the file). In this lab we will practice creating, throwing and handling exceptions. 1. Combination Lock A combination lock (like the one in Figure 1) is a lock with a dial for which a series of numbers (which together are called a combination) are used to unlock it. Each lock has a dial range (which is the range of numbers in the dial, from 0 up to an upper limit), and an unlocking combination to unlock it (which for simplicity in our case is a sequence of 3 numbers). Since an unlocking combination must have only numbers that are in the dial, a lock can only be created if its unlocking combination is a valid combination which is one in which all its numbers are in the dial. For example, the combination { 2, 9, 1 } is valid if assigned to a lock whose dial goes from 0 to 9, but is invalid if it is assigned to a lock whose dial only goes up to 5. Figure 1. Combination lock. Once created, locks can receive opening combinations for unlocking; as expected, if an opening combination is not the same as the unlocking combination then the lock does not open. Your task is to create classes that mimic the behavior of a lock while making use of exceptions.
Exercise 1 1. Create a Lab05 project. 2. Create a class Combination. This is a class that simply stores 3 integers (making a lock combination), and implements the methods below: A constructor receiving 3 integer numbers (each as a separate parameter), which together represent a lock combination. The order of these numbers is important to open the lock. The method getnumbers, which returns a primitive array with numbers in the lock combination. The method iswithinrange, which receives an integer indicating an upper limit; and returns a boolean indicating whether all 3 numbers in the combination are in the range [0, upper limit] (including boundaries); true is returned if the 3 numbers are in range, false otherwise. The method equals, which overrides the homonymous method from Object. The method receives an object and returns a boolean indicating whether the object received is equal to this combination, which would be true if both have the same 3 numbers in the same order. 3. Create a class InvalidLockCombinationException that subclasses from Java s RuntimeException. This exception (which should not have any methods) will indicate that an attempt to assign a combination to a lock failed (thus making the combination invalid for that lock). 4. Create a class Lock. Locks have an unlocking combination, an upper limit for the rotating dial, and a value indicating whether they are opened or closed. This class implements the methods below: A constructor receiving the upper limit and unlocking combination. If the combination is invalid (if not all its numbers are in the dial) then the constructor should throw a new InvalidLockCombinationException. By throwing this exception we can avoid creating locks with invalid combinations (which in real life will be defective). All locks are open when created. The method getdiallimit, which returns the upper limit of the rotating dial. The method open, which receives an opening combination and opens the lock only if it is equal to the unlocking combination (hint: use the equals method from the Combination class). An opened lock will remain opened regardless of the opening combination received. The method close, which closes the lock. The method isopen, which returns a boolean indicating whether the lock is opened or not. 5. Download the JUnit test files CombinationTest.java and LockTest.java from the class website and import them into the project. Test your methods using their test cases. Get your instructor s signature when all tests pass. Exercise 1 - Get Instructor s Signature
Locks That Can Be Reset The lock business has been on the rise. However, sophisticated customers now want locks whose combination can be changed. To satisfy this market niche, you are extending the Lock class to allow locks whose combination can be reset. Figure 2. Dialog requesting a new combination. The new class will define 2 methods to read new combinations: resetnaive and resetretry. Both methods will display the JOptionPane dialog shown in Figure 2, will use a Scanner object to parse the input to numbers, and then use these numbers as the new combination for the lock. The difference between them is that resetnaive will assume that the input is always correct and will not check for exceptions, whereas resetretry will catch exceptions and recover from them by allowing the user to try typing the combination again. To display the JOptionPane dialog shown in Figure 2 look at the JOptionPane class in the Java API and use one of its showinputdialog methods: the simplest case takes null as its parent component, and the string Type a new combination as its message. Once displayed, this dialog can result in either the user canceling it, or the user typing something and pressing OK. When the dialog is cancelled, it returns a null value; thus we can use null as an indication that the user does not want to change the lock s combination. On the other hand, that the result of the dialog is not null indicates that there is an input that the user wants to use as the new combination of the lock. This is the point where the 2 methods will diverge. On the one hand, the method resetnaive will (naively) assume that the input is always given in the form of 3 integers separated by spaces and will proceed to use Scanner to read them and create a new combination. We know that careless users could types fewer than 3 numbers or could type letters instead of numbers or type 3 numbers that create an invalid combination for this lock. But that is ok; we want this method to fail and throw exceptions when they happen. The method resetretry will do exactly as resetnaive did but it will catch exceptions and show a message dialog indicating that the input was incorrect before displaying the input dialog again. Users can retry for as long as the input dialog is not canceled or a valid combination is provided. The implementation details of these methods are described next. Exercise 2 1. Go back to the class Lock and make the field that holds the unlock combination a protected field. 2. Create a class LockWithReset that subclasses from Lock. This class implements the methods below: A constructor that receives as parameters an upper limit for the dial and a combination, and invokes its super- class constructor using this data.
Figure 4. Message dialog indicating a NoSuchElementException. Figure 4. Message dialog indicating an InvalidLockCombinationException. The method resetnaive, which should display the input dialog from Figure 2 and (if the user does not cancel it) process its input to create a new combination. If the user cancels (the JOptionPane returns null), the method should terminate normally. Otherwise, use Scanner to read the three integers and use them to create a new combination. As mentioned earlier, this method should not make any attempts to recover from exceptions when scanning the input. If the input does not have 3 numbers then the method should throw a NoSuchElementException. If the input has 3 numbers but they do not make a valid combination for the lock then the method should throw an InvalidLockCombinationException. The method resetretry, which should also display the input dialog from Figure 2 and (if the user does not cancel it) process its input to create a new combination. resetretry, however, should catch exceptions and allow the user to re- enter a combination (upon failure). Although you re free to implement this method in any way you want, it is best to reuse resetnaive. Use a while loop to call this method and loop until there are no exceptions thrown. The method should show the message dialog in Figure 3 if a NoSuchElementException (thrown by Scanner) or the message dialog in Figure 4 if an InvalidLockCombinationException (from an invalid combination) is caught, before showing the input dialog in Figure 2 again. The dialogs shown in Figure 3 & Figure 4 are JOptionPane message dialogs. To program them use any of the showmessagedialog methods in the JOptionPane class. A static method main, which you can use to test your methods before attempting the automated JUnit tests (next step). You can initially use the main method below and later change the last statement to invoke the method resetretry instead: public static void main(string[] args) { Combination c = new Combination( 1, 2, 3 ); LockWithReset lock = new LockWithReset( 5, c ); } lock.resetnaive(); 3. Download the JUnit test file LockWithResetTest.java from the class website and import it into the project. Note that besides adding junit to the Build Path, you will also need to download and add an external library to make this test file compile and work. As such, direct your web browser to https://github.com/robertoaflores/gooey/ and follow instructions to download the JAR file gooey.jar (ask your instructor what JAR means if you haven t heard this term before). Once the JAR file has been downloaded, go back to Eclipse and right- click on your Lab05 project; choose the
options Build Path and Add External Archives. Direct the file dialog that appears to the location where you downloaded the JAR file. As shown in Figure 5, selecting this file should add a new project branch named Referenced Libraries, which should contain Gooey s JAR file. There should not be any compile errors in the JUnit test file at this point. Test your methods using the JUnit test cases. Note that the tests will briefly display your JOptionPane dialogs when testing. They will disappear when the tests end. Get your instructor s signature when all tests pass. Figure 5. Gooey added to the Project as a Referenced Library. Exercise 2 - Get Instructor s Signature
Lab 5 Instructor s Signature Page Student s Name: Student ID Exercise 1: JUnit tests passed: Exercise 2: JUnit tests passed: