CPE 102

Winter 2007

Program 5

 

Due Date

 

You must turn in a functionally correct program to receive any credit.  The grade you receive will be based on when you turn it in minus any deductions for the quality of your implementation and/or multiple submissions.  There is no deduction for the first submission and a 5% deduction for each additional submission, if any.  Programs will be checked for correctness once a day and you will be notified by email if your submission is not functionally correct.  Programs will be graded after the last due date and the results will be emailed to you within a few days of that date.

 

100% (minus any deductions) by 9:00pm Monday, 2/11/08

90% (minus any deductions) by 9:00pm Tuesday, 2/12/08

80% (minus any deductions) by 9:00pm Wednesday, 2/13/08

70% (minus any deductions) by 9:00pm Thursday, 2/14/08

  

Errata

 

None

                              

Objectives

 

 

Resources

 

  1. Java Standard API
  2. P5TestDriver.java  (will be published Monday 2/11)
  3. P5UnitTests.zip
  4. Necessary input files for the test driver - you can examine these for examples of well-formed comma-delimited text files:
    1. BadQuantityBook.txt
    2. BadQuantityBookOnTape.txt
    3. BadQuantityCD.txt
    4. Duplicates.txt
    5. GoodNegativeQuantities.txt
    6. MissingProduct.txt

 

Problem Description

 

  1. You will be modifying and enhancing your Program 4 source code in several ways.  First, you will be detecting, reporting and, in some cases, handling several error conditions with both checked and unchecked exceptions that you create.  You will also be working with character streams to read and write comma-delimited text files that contain complete product specifications.  Finally, you will also be overriding the equals() method for the Inventory class

    IMPORTANT
    : When running the provided test driver you will need six text file (see Resources section above for links) to be in the directory where the .class files of your solution are found.
  2. JUnit tests will be provided in P5UnitTests.zip.  Replace the stubbed out versions of InventoryTest, BookOnTapeTest, and CDTest with the tests you wrote in Program 4.  These versions will now need to be extended to test additional methods that you write.  Recall from Program 1, one of the Fraction constructors threw an exception.  In FractionTest, a JUnit test was written for when we expected that exception to be thrown.  In your InventoryTest class, you will come upon a similar dilemma.  The syntax for expected an exception to be thrown in your test case is @Test(expected=<TheNameOfYourException>.class).  JUnit tests with this annotation will ONLY run successfully if the exception IS thrown.  Refer to FractionTest in Program 1 as an example.

 

Suggestions

 

  1. Make sure your Program 4 code successfully passes all of the Program 3 tests before moving on to the Program 5 modifications
  2. Then, and only then, COPY all Program 4 source files to a new project and begin making the Program 5 modifications.
  3. You can (and probably should) attemp to parse the comma-delimited input fiiles in a seperate program (without inheritance to add to the confusion) to learn how to use the Scanner class and String class to get the job done.  Once you understand the process in the simplier environment it should be much easier to implement in the class hierarchy of Program 5.
  4. Remember to use the tests and given documentation to understand the conditions in which your implementation should work.
  5. Follow the test-driven development style by first reading the given JUnit test for the method you want to implement, then implement that method's functionality and watch the test pass.  If the test is not given, then write the test for how the method should work, see that it fails (since you have not written the code yet), then write the code to pass the test.
  6. Keep track of your hours worked as you go, so you don’t have to guess when you hand in your assignment (see handin section below for information on time.txt).

 

Specification

 

  1. You must implement the classes, interfaces, and methods exactly as described or the provided test driver will not work!

 

  1. Add the add @throws tags to the javadoc-style documentation in the Inventory class as appropriate.  Be sure to update any javadoc comments in the Inventory class to reflect the changes you are making for this program.

 

  1. Do not reinvent the wheel.  Demonstrate knowledge of the Java Standard Library classes you are working with.  When and wherever appropriate use code that has already be written and tested for you!  Your program will be graded with this in mind!

 

  1. Create the following checked exceptions:

 

    1. DuplicateProductIDException – This exception should be constructed with the following message:

 

Product ID XXXXXX is already in the inventory

 

Where XXXXXX is replaced with the actual duplicate product ID

 

    1. DuplicateProductException – This exception should be constructed with the following message:

 

Product ID XXXXXX is equivalent to existing Product ID YYYYYY

 

Where XXXXXX is replaced with the ID of the product that is being added and YYYYYY is replaced with the ID of the equivalent product already in the inventory.

 

  1. Create the following unchecked exceptions:

 

    1. MissingProductException – This exception should be constructed with the following message:

 

Can not find Product ID XXXXXX

 

Where XXXXXX is replaced with the product ID that cannot be found in the inventory.

 

    1. InsufficientProductException – This exception should be constructed with the following message:

 

Product only has XXX units, need YYY

 

Where XXX is the quantity of product on hand and YYY is the amount of product requested.

 

  1. Change the return type of Inventory.addNew(Product) from boolean to void.

 

    1. The method should now throw a DuplicateProductIDException if someone tries to add a product with an ID that already exists in the inventory.

 

    1. The method should now throw a DuplicateProductException if someone tries to add a logically equivalent product using the equals() method as defined for Program 2.  Recall that this means all attributes are equal except product-ID and quantity.

 

  1. Change the return type of Inventory.addInventory(int, int) from boolean to void.

 

    1. The method should now throw a MissingProductException if someone tries to update the quantity of a product that does not exist in the inventory.

 

    1. The method should now throw an InsufficientProductException if someone tries to adjust the quantity to a value less than zero.  In such a case, the quantity should remain unchanged.

 

  1. Override the equals(Object) method of Object in the Inventory class.  This should be a well-formed equals() implementation that correctly compares the only instance variable of the class (an ArrayList of inventory).  This method should return true if the two Inventory objects have the same products in the same order based on the product’s equals() method.  Think about the efficiency of your solution.  Read about the equals method of the ArrayList class to see if it is sufficient!  If it is, you should use it, otherwise you should implement you own logic – ask me if you are not sure!

 

  1. Write a new Java interface called DelimitedTextIO with the following methods:

 

    1. String toText(char delimiter) – This method returns a String containing all the data of the implementing class as text and with each element separated by the provided delimiter.

 

    1. void toObject(Scanner input) – This method uses the Scanner parameter to parse delimited text representing the data for the implementing class and initializes the objects instance variables with the parsed values.  The delimiter to use must be set for the Scanner object being used for input before passing it to this method.  I strongly suggest you use the method that accepts a String defining the delimiter unless you are very familiar with Regular Expressions.  Read the javadocs for the Scanner class to find the method necessary for doing this.   This method will handle any amount of white-space before and/or after any token in the input by removing it - you may want to use the trim method of the String class to help you with this task.

 

  1. Implement the DelimitedTextIO interface in the Product class and the Name class.  Implement its methods in Product and Name and override them in any necessary subclass as follows:

 

    1. The toText method should return a comma-delimited String (a single comma - not a comma-space) in the order specified below for each specific product.  You can include extra whitespace before and after the delimeter for readability (as in the example below) but it is not required.  Replace the names of the variables in the example below with the object’s actual values for those instance variables.  Notice that the Name objects must be output in the order specified (you can and should use the toText method implemented in Name to do this) - do not include the parenthesis in your String. Take a look at some of the provided text files to help you understand this specification clearly and exactly before you begin coding.  You must demonstrate that you understand inheritance and overriding methods in your implementation – this means you must not use any accessor methods (other than toText) of Product, any of its subclasses, or Name.  Recall that you can use the getClass().getName() call to obtain the name of any class at runtime.

 

“Book, product ID, quantity, description, wholesale price, retail price, title, publisher, author (last, first, middle), type, pages, binding”

 

“BookOnTape, product ID, quantity, description, wholesale price, retail price, title, publisher, author (last, first, middle), type, reader (last, first, middle), length, format”

 

“CD, product ID, quantity, description, wholesale price, retail price, title, artist (last, first, middle)”

 

    1. The toObject method should use the provided Scanner to reverse the process of toText above.  Be sure your solution works with and without whitespace before and/or after the delimiter. You must demonstrate that you understand inheritance and overriding methods in your implementation – this means you must not use any accessor methods (other than toObject) of Product, any of its subclasses, or Name.

 

    1. Implement DelimitedTextIO interface and its methods, toText and toObject, in Name as well.  The order of the instance variables must be last, first, middle.

 

  1. Add the following new methods to the Inventory class:

 

    1. public boolean contains(int productID) – This method should return true if the inventory contains a product with the specified productID, otherwise false.

 

    1. public void writeCommaDelimitedInventory(String filename) – This method must write every product in the inventory to a text file as comma-delimited text with one product per line.  It must make use of the toText method written in Product, its subclasses, and Name. If, after thinking about it sufficiently, you do not know how to do this you may ask you instructor for clarification. You can examine the provided comma-delimited input files for examples of what your output should look like (see Resources section above).  The data must be written in exactly the order specified depending on product class type.

 

    1. public ArrayList addNew(String filename) – This method must read comma-delimited text files in the format specified for the toText method of Product class, its subclasses, and Name class.  It must make use of the toObject method written in Product, its subclasses, and Name. If, after thinking about it sufficiently, you do not know how to do this you may ask you instructor for clarification.  

 

      1. After constructing and initializing the correct kind of product for each line read from the text file this method should attempt to add the product to the inventory using the addNew(Product) method of the Inventory class.

 

      1. This method should handle any exceptions that may be thrown by addNew(Product) by creating a String object containing the 1-based line-number of the input causing the exception and the actual comma-delimited text of the input.  These Strings should be added to an ArrayList<String> and returned to the caller of the method.  The format of the error String is as follow:

 

Line XX – “Replace this with the actual comma-delimited Product text here from its toText method”

 

Where  “XX” with the 1-based line-number of the comma-delimited text in input file.  This means the first line in the text file is considered to be line 1, not line 0.

 

    1. public ArrayList addInventory(String filename) – This method should read comma-delimited text in the format specified for the toText method of Product class, its subclasses, and Name class.

 

      1. After reading in the product it should attempt to change the quantity of the matching product, if any, in the inventory using the addInventory(int, int) method.

 

      1. This method should handle any exceptions that may be thrown by addInventory(int, int) by creating a String object containing the 1-based line-number of the input causing the exception and the actual comma-delimited text of the input.  These Strings should be added to an ArrayList<String> and returned to the caller of the method.  The format of the error String is as follows:

 

Line XX – “Replace this with the actual comma-delimited Product text from the input-file here

  

Where  “XX” with the 1-based line-number of the comma-delimited text in input file.  This means the first line in the text file is considered to be line 1, not line 0.

 


Testing With the Provided Tests

 

  1. Your code must be 100% correct to recieve credit.  Correctness will be determined by running the acceptance test P5TestDriver.java to be published Monday 2/11.  
  2. In addition to the acceptance test, sections 7 and 9 will be graded on the quality of JUnit tests they create for this program, section 3 will not.
  3. Use the JUnit tests while developing in a test-driven approach to ensure your code's correctness before the acceptance test is released.  Run them by opening the AllTests.java file and executing it.
  4. Ask your instructor for assistance if you are not able to run these tests on your own.

Handing in Your Source Electronically…

 

  1. Create a plain text file called time.txt to log the amount of time spent on the assignment.  The file will contain only three lines with the following information on each line: name, project number, hours spent.
                 Example time.txt file:  
             Sally Student
             Program 5
             7.5 hours
  1. Move the necessary file(s) to your vogon account using your favorite FTP client program.

 

  1. Log on to vogon using your favorite Shell client program.

 

  1. Change directory (cd-command) to the directory containing the file(s) to hand in.  Be sure you code compiles and runs correctly on hornet before turning it in!

 

  1. Use the following handin command being sure to:

 

    1. Replace the x with the correct maximum score you can earn based on the due date, i.e., replace y with 100 if you are handing in by Monday’s deadline, 90 for Tuesday, 80 for Wednesday, or 70 for Thursday, for example Program5-100, Program5-90, et cetera.

 

12:01pm vogon ~$ handin graderkm Program5-x Inventory.java Product.java AbstractBook.java Book.java BookOnTape.java CD.java Name.java DuplicateProductIDException.java DuplicateProductException.java MissingProductException.java InsufficientProductException.java DelimitedTextIO.java BookOnTapeTest.java InventoryTest.java CDTest.java time.txt