Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Program Description: This assignment will give you practice writing Java classes to a provided API and using Collections. You are to write a set of

Program Description:

This assignment will give you practice writing Java classes to a provided API and using Collections. You are to write a set of supporting classes for a simple shopping cart. The instructor has provided the Graphical User Interface (GUI) that will provide the "front end" or "view" to your program. You are to write the back end (what is often referred to as the "domain specific code" or the model).

Here is a screen shot of what the program could look like when the user has selected various items to order (note that the exact appearance may be platform dependent):

Prices are expressed as real numbers and quantities are expressed as integers (i.e., you cant buy 2.345 units of something). Notice that some of the items have a discount when you buy more. For example, Silly Putty normally costs $4.41 per unit, but you can buy 6 for $10.04. These items have, in effect, two prices: a single item price and a bulk item price for a bulk quantity. When computing the total with the bulk item discount, apply as many of the bulk quantity as you can and then use the single item price for any leftovers. For example, the user is ordering 12 buttons that cost $0.95 each but can be bought in bulk at 10 for $5.00. The first 10 are sold at that bulk price ($5.00) and the two extras are charged at the single item price ($0.95 each) for a total of $6.90. If the user were ordering 22 buttons, the total would be $11.90 (two bulk quantities plus two extras).

At the bottom of the GUI there is a checkbox for a discount for customers who have a store membership. If this box is checked, a 10% discount is applied to the total value of the ShoppingCart if that total value is greater than $20.00

For example, if we select that checkbox, the GUI looks like this:

Implementation Guidelines:

Your task is to implement the three classes that are used to make this code work:

Item ItemOrder ShoppingCart

An Item object stores information about an individual item. It must have the following public methods. Note that the names (such as price and bulk quantity) given here are not meant to be the actual parameter names (Checkstyle would complain about them); theyre meant to be descriptive.

Method

Description

Item(name, price)

Constructor that takes a name and a price as arguments. The name is a String and the price is a BigDecimal.

Item(name, price, bulk quantity, bulk price)

Constructor that takes a name, a single-item price, a bulk quantity, and a bulk price as arguments. The name is a String, the quantity is an int and the prices are BigDecimal s.

getName()

Returns the name for this Item. (String return type)

getPrice()

Returns the single item price for this Item. (BigDecimal return type)

getBulkQuantity()

Returns the bulk quantity for this Item. (int return type)

getBulkPrice()

Returns the bulk price for this Item. (BigDecimal return type)

isBulk()

Returns True if the Item has bulk pricing; false otherwise

toString()

Returns a String representation of this Item: name, followed by a comma and a space, followed by price. If the item has a bulk price, you should append an extra space and a parenthesized description of the bulk pricing that has the bulk quantity, the word for and the bulk price. See the examples below.

equals(object)

Returns true if the specified object is equivalent to this Item, and false otherwise. Two items are equivalent if they have exactly equivalent

names, prices, bulk quantities and bulk prices. This method must properly override java.lang.Object.equals().

hashCode()

Returns an integer hash code for this item. This method must override java.lang.Object.hashCode() and be consistent with equals().

The String representation of an Item must exactly match that shown in the screenshots. For example, an Item named X with a per-item price of $19.99 and no bulk quantity would have the String representation X, $19.99 (without the quotes); an item named X with a per-item price of $19.99, a bulk quantity of 5, and a bulk price of $89.99 would have the String representation X, $19.99 (5 for $89.99) (without the quotes). The format of these String representations will be tested.

An ItemOrder object stores information about a purchase order for a particular item: namely, a reference to the item itself and the quantity desired. It must have the following public methods.

Method

Description

ItemOrder(item, quantity)

Constructor that creates an item order for the given quantity of the given Item. The quantity is an int.

getItem()

Returns a reference to the Item in this ItemOrder.

getQuantity() 

Returns the quantity for this ItemOrder.

toString()

Returns a String representation of this ItemOrder: You may use any format that seems reasonable to you for this String.

A ShoppingCart object stores information about the customer's overall purchase. One field must be a collection of some type to hold information about all the Items the customer has ordered. (Use a generic

collection from the Java Collections Framework. One possible choice, though perhaps not the easiest to work with, is List). ShoppingCart class must have the following public methods.

Method

Description

ShoppingCart() 

Constructor that creates an empty shopping cart.

add(order)

Adds an order to the shopping cart, replacing any previous order for an equivalent item with the new order. The parameter is an ItemOrder. (equals() would return true if used to compare equivalent items) The return type of this method is void

setMembership(value)

Sets whether or not the customer for this shopping cart has a store membership (the parameter is a boolean; true means the customer has a membership, false means the customer doesnt). The return is void.

calculateTotal()

Returns the total cost of this shopping cart as a BigDecimal. This

returned BigDecimal should have scale of 2 and use the ROUND_HALF_EVEN rounding rule.

clear()

Removes all orders from the cart. The return is void.

toString()

Returns a String representation of this ShoppingCart: You may use any format that seems reasonable to you for this String.

You must not change any method signatures or return types defined in this assignment. (You may change parameter names but not parameter data types.) You must not introduce any other non-private methods to these classes, although you may add your own private helper methods. You must override toString in these classes (you may find this helpful for testing and debugging). You are also allowed to override other (non-final) methods declared in java.lang.Object, such as equals and hashCode. If you do, however, your definitions must be reasonable and consistent with each other; if you implement inconsistent equals and hashCode methods, you will certainly lose points. You must override equals and hashCode for the Item class, as described above (this will be tested when I grade your assignment even if you dont actually use those methods in your own code).

For this assignment you do NOT need to code defensively:

That is, you can trust that my GUI code will never pass invalid parameters to setters or constructors in your code.

You are required to develop unit tests for the Item class (it is recommended that you also do this for the ItemOrder and ShoppingCart classes). This will allow you to develop these classes in stages rather than all at once. When you have confidence that your classes are working, you should combine them with the set of classes developed by the instructor to make sure that they are working properly when combined. Place your unit tests in the 'tests' package.

Hints and Suggestions:

As you develop your classes do not code any dependencies based on the current list of items. That is, your classes should still work correctly if the list of items is replaced with an entirely different list of items.

Most of these methods are fairly simple to write, but notice that when you add an ItemOrder to a ShoppingCart you have to deal with replacing any old order for an equivalent item. A user might initially request 3 of some item and later change the request to 5 of that item. The order for 5 replaces the order for 3. The user is not requesting 8 of the item when he makes such a change. The add method might be passed an item order with a quantity of 0. This should behave just like the others, replacing any current order for the item.

One technique (which is not the best one, but will certainly work) is to use an ArrayList to implement your ShoppingCart. If you do, the methods you are most likely to be interested in are the following:

Method

Description

ArrayList() 

Constructor that creates an empty ArrayList to hold elements of type T.

add(value)

Adds the given value to end of the ArrayList. The parameter type is T, so only the type you specified at construction can be added to the ArrayList.

get(index)

Gets the item at the given index (0-based). The return type is T.

set(index, value)

Sets the entry at the given index to be the given value.

remove(index)

Removes the value at the given index.

toString()

Returns a string representation of the list.

size()

Returns the number of values stored in the list.

In the Item class, you need to construct a String representation of the price. This is not easy to do for a number of reasons, but Java provides a convenient built-in class that will do it for you. It is called NumberFormat and is part of the java.text package (so you need to import java.text.NumberFormat). You obtain a number formatter by calling the static method named getCurrencyInstance(), as in:

NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US); You can then call the format method of this object, passing it the price as a BigDecimal, and it will return a

String with a dollar sign and the price in dollars and cents. For example, you might say: BigDecimal price = BigDecimal.valueOf(38.50);

String text = nf.format(price);

This would set the variable text to "$38.50". Note that you only need one NumberFormat reference, and you can use it repeatedly. Do not create a number formatter every time you need to format a number, as that would be wasteful of memory (and would cost you points for redundancy in your implementation). Instead make a single NumberFormat reference that can be shared by all Item objects. An alternate acceptable way to

format the output would be to use the format() method of the String class.

Your classes are to exactly reproduce the format and overall price shown in the two screenshots and described above. You will have to run the GUI and enter the individual quantities from the screenshots to verify that your classes are working correctly (and / or write a unit test that does so). Note that the values shown in the

4

screenshots are not the only values your program will be tested with (and, in fact, the list of items in the screenshots is not the only list of items your classes will be tested with).

NOTE: No console output should appear when running the program or when running your unit tests.

Stylistic Guidelines:

You will be graded on program style, including the use of descriptive variable names and full Javadoc comments on each method. Note that the class skeletons provided for you have no comments of any kind; adding the comments is a critical part of the assignment. The provided ShoppingFrame and ShoppingMain classes have full Javadoc comments that would be considered acceptable in a homework submission.

Notice that the provided classes (other than the skeletons you must fill in) have no Checkstyle, FindBugs, PMD, or Metrics warnings. It is generally a good idea to eliminate all warnings before submitting your code; if you have questions about what a particular warning means, and a quick online search doesnt help, ask the instructor as soon as possible (preferably by posting your question on the Canvas discussion forum without posting actual code from your project).

You must include a header comment at the beginning of each file with some basic information, in addition to full Javadoc comments. Examples of acceptable file headers (including the class Javadoc comment) appear in Assignment 0 and in the provided ShoppingFrame and ShoppingMain classes.

Submission and Grading:

Create your Eclipse project by downloading the hw2-project.zip file from Canvas, importing it into your workspace (as described for hw0-project.zip in Assignment 0), and using Refactor to change username

in the project name to your UWNetID. Remember to make this change before you first commit the project to Subversion. As with Assignment 0, incorrectly-named projects will be penalized.

Also as with Assignment 0, you can use whichever bracket style you like. The provided templates and classes use the same line style; if you switch the line style, execute a Format command (in Eclipses Source menu) for each source file after doing so to change the provided templates and classes.

You must check your Eclipse project into Subversion (following the instructions from Lecture 1 and Assignment 0), including all configuration files that were supplied with it (even if you have not changed them from the ones that were distributed). If you have any questions about this, ask the instructor as soon as possible. When you have checked in the revision of your code you wish to submit, make a note of its Subversion revision number. To get the revision number, perform an update on the top level of your project; the revision number will then be displayed next to the project name. Your revision number will pick up where you left off on Assignment 1; if you submitted revision 12 of Assignment 1, the first commit of Assignment 2 will have a number greater than 12. This is because you have a single Subversion repository for all your projects, and the revision number counts revisions to the entire repository.

After checking your project into Subversion, you must submit (on Canvas) an executive summary, containing the Subversion revision number of your submission, an assignment overview (1 paragraph, up to about 250 words) explaining what you understand to be the purpose and scope of the assignment, and a technical impression section (1-2 paragraphs, about 200-500 words) describing your experiences while carrying out the assignment.

The filename for your executive summary must be username-shoppingcart.txt, where username is your UWNetID. As with the naming convention for your Eclipse project, your assignment will be penalized if it

does not follow this naming convention. An executive summary template, which you must use, is available on Canvas. In particular, your executive summary must have a line containing exactly the text Subversion Revision Number: #, with no leading spaces, where # is the Subversion revision number you made a note of above (with no parentheses or other symbols). Executive summaries without a line following this exact format will be penalized. Executive summaries will only be accepted in plain text format other file formats (RTF, Microsoft Word, Acrobat PDF, Apple Pages) are not acceptable. Using an unacceptable file format for the executive summary will result in a reduction in the grade for the assignment.

Part of your program's score will come from its "external correctness." For this assignment, external correctness is measured by the output generated (correct calculations, correct behavior when values are entered, changed and deleted, correct discount behavior, etc.), and is determined by running automated tests on your code.

Another part of your program's score will come from its "internal correctness." Internal correctness includes meaningful and systematically assigned identifier names, proper encapsulation, avoidance of redundancy, good choices of data representation (though this is not really applicable to this assignment), the use of comments on particularly complex code sections, and the inclusion of headers (as described above) on your classes. Internal correctness also includes whether your source code follows the stylistic guidelines discussed in class. This includes criteria such as the presence of Javadoc comments on every method and field (even private ones!), the use of variable names, spacing, indentation, and bracket placement specified in the class coding standard, and the absence of certain common coding errors that can be detected by the tools. It is therefore to your advantage to be sure the plugin tools like your code before you submit it.

Item.java

// Finish and comment me! // Add whatever fields you think are necessary.

package model;

import java.math.BigDecimal;

public final class Item { public Item(final String theName, final BigDecimal thePrice) {

}

public Item(final String theName, final BigDecimal thePrice, final int theBulkQuantity, final BigDecimal theBulkPrice) {

}

public String getName() { return null; } public BigDecimal getPrice() { return null; }

public int getBulkQuantity() { return 0; }

public BigDecimal getBulkPrice() { return null; }

public boolean isBulk() { return false; }

@Override public String toString() { return null; }

@Override public boolean equals(final Object theOther) { return false; }

@Override public int hashCode() { return 0; }

}

ItemOrder.java

// Finish and comment me! // Add whatever fields you think are necessary.

package model;

public final class ItemOrder {

public ItemOrder(final Item theItem, final int theQuantity) {

}

public Item getItem() { return null; } public int getQuantity() { return 0; }

@Override public String toString() {

return null; }

}

ShoppingCart.java

// Finish and comment me! // Add whatever fields you think are necessary.

package model;

import java.math.BigDecimal;

public class ShoppingCart {

public ShoppingCart() {

}

public void add(final ItemOrder theOrder) { }

public void setMembership(final boolean theMembership) { }

public BigDecimal calculateTotal() {

return null; } public void clear() { }

@Override public String toString() { return null; }

}

FileLoader.java

package utility;

import java.io.IOException; import java.math.BigDecimal; import java.nio.file.Paths; import java.util.LinkedList; import java.util.List; import java.util.Scanner;

import model.Item;

/** * A utility class for The shopping cart application. * * @author Charles Bryan * @version Autumn 2015 */ public final class FileLoader { /** * A private constructor, to prevent external instantiation. */ private FileLoader() { } /** * Reads item information from a file and returns a List of Item objects. * @param theFile the name of the file to load into a List of Items * @return a List of Item objects created from data in an input file */ public static List readItemsFromFile(final String theFile) { final List items = new LinkedList<>(); try (Scanner input = new Scanner(Paths.get(theFile))) { // Java 7! while (input.hasNextLine()) { final Scanner line = new Scanner(input.nextLine()); line.useDelimiter(";"); final String itemName = line.next(); final BigDecimal itemPrice = line.nextBigDecimal(); if (line.hasNext()) { final int bulkQuantity = line.nextInt(); final BigDecimal bulkPrice = line.nextBigDecimal(); items.add(new Item(itemName, itemPrice, bulkQuantity, bulkPrice)); } else { items.add(new Item(itemName, itemPrice)); } line.close(); } } catch (final IOException e) { e.printStackTrace(); } // no finally block needed to close 'input' with the Java 7 try with resource block return items; }

/** * Reads item information from a file and returns a List of Item objects. * @param theFile the name of the file to load into a List of Items * @return a List of Item objects created from data in an input file */ public static List readConfigurationFromFile(final String theFile) { final List results = new LinkedList<>(); try (Scanner input = new Scanner(Paths.get(theFile))) { // Java 7! while (input.hasNextLine()) { final String line = input.nextLine(); //if (!line.startsWith("#")) { if (!(line.charAt(0) == '#')) { results.add(line); } } } catch (final IOException e) { e.printStackTrace(); } // no finally block needed to close 'input' with the Java 7 try with resource block return results; } }

ShoppingFrame.java

/* * TCSS 305 Assignment 2 - Shopping Cart */

package view;

import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent;

import java.text.NumberFormat; import java.util.LinkedList; import java.util.List;

import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingConstants;

import model.Item; import model.ItemOrder; import model.ShoppingCart;

/** * ShoppingFrame provides the user interface for a shopping cart program. * * @author Marty Stepp * @author Daniel M. Zimmerman (Formatting and Comments) * @author Alan Fowler (Numerous changes to code and comments including use of BigDecimal) * * @version Autumn 2016 */ public final class ShoppingFrame extends JFrame { /** * A generated serialization id. */ private static final long serialVersionUID = 4479585442295889730L;

// constants to capture screen dimensions /** A ToolKit. */ private static final Toolkit KIT = Toolkit.getDefaultToolkit(); /** The Dimension of the screen. */ private static final Dimension SCREEN_SIZE = KIT.getScreenSize();

/** * The width of the text field in the GUI. */ private static final int TEXT_FIELD_WIDTH = 12; /* * For the UW color palette and other UW branding information see * http://www.washington.edu/marketing/files/2012/09/WebColorPalette1.pdf */ /** * The color for some elements in the GUI. */ private static final Color UW_GOLD = new Color(199, 153, 0);

/** * The color for some elements in the GUI. */ private static final Color UW_PURPLE = new Color(57, 39, 91);

/** * The shopping cart used by this GUI. */ private final ShoppingCart myItems; /** * The list that stores the inventory. */ private final List myInventory; /** * The text field used to display the total amount owed by the customer. */ private final JTextField myTotal;

/** * A List of the item text fields. */ private final List myQuantities; /** * Initializes the shopping cart GUI. * * @param theInventory The list of Items. */ public ShoppingFrame(final List theInventory) { super(); // No title on the JFrame. We can set this later. myItems = new ShoppingCart();

// set up text field with order total myTotal = new JTextField("$0.00", TEXT_FIELD_WIDTH); myQuantities = new LinkedList<>(); myInventory = theInventory; setupGUI(); }

/** * Setup the various parts of the GUI. */ private void setupGUI() { // replace the default JFrame icon final ImageIcon img = new ImageIcon("files/w.gif"); setIconImage(img.getImage()); setTitle("Shopping Cart"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); add(makeTotalPanel(), BorderLayout.NORTH); final JPanel itemsPanel = makeItemsPanel(myInventory); add(itemsPanel, BorderLayout.CENTER); add(makeCheckBoxPanel(), BorderLayout.SOUTH);

// adjust size to just fit pack(); // make the GUI so that it cannot be resized by the user dragging a corner setResizable(false); // position the frame in the center of the screen setLocation(SCREEN_SIZE.width / 2 - getWidth() / 2, SCREEN_SIZE.height / 2 - getHeight() / 2); setVisible(true); }

/** * Creates a panel to hold the total. * * @return The created panel */ private JPanel makeTotalPanel() { // tweak the text field so that users can't edit it, and set // its color appropriately

myTotal.setEditable(false); myTotal.setEnabled(false); myTotal.setDisabledTextColor(Color.BLACK);

// create the panel, and its label

final JPanel totalPanel = new JPanel(); totalPanel.setBackground(UW_PURPLE); final JLabel l = new JLabel("order total"); l.setForeground(Color.WHITE); totalPanel.add(l); totalPanel.add(myTotal); final JPanel p = new JPanel(new BorderLayout()); p.add(totalPanel, BorderLayout.CENTER); return p; }

/** * Creates a panel to hold the specified list of items. * * @param theItems The items * @return The created panel */ private JPanel makeItemsPanel(final List theItems) { final JPanel p = new JPanel(new GridLayout(theItems.size(), 1)); for (final Item item : theItems) { addItem(item, p); }

return p; }

/** * Creates and returns the checkbox panel. * * @return the checkbox panel */ private JPanel makeCheckBoxPanel() { final JPanel p = new JPanel(); p.setBackground(UW_PURPLE); final JButton clearButton = new JButton("Clear"); clearButton.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent theEvent) { myItems.clear(); for (final JTextField field : myQuantities) { field.setText(""); } updateTotal(); } }); p.add(clearButton); final JCheckBox cb = new JCheckBox("customer has store membership"); cb.setForeground(Color.WHITE); cb.setBackground(UW_PURPLE); cb.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent theEvent) { myItems.setMembership(cb.isSelected()); updateTotal(); } }); p.add(cb); return p; }

/** * Adds the specified product to the specified panel. * * @param theItem The product to add. * @param thePanel The panel to add the product to. */ private void addItem(final Item theItem, final JPanel thePanel) { final JPanel sub = new JPanel(new FlowLayout(FlowLayout.LEFT)); sub.setBackground(UW_GOLD); final JTextField quantity = new JTextField(3); myQuantities.add(quantity); quantity.setHorizontalAlignment(SwingConstants.CENTER); quantity.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent theEvent) { quantity.transferFocus(); } }); quantity.addFocusListener(new FocusAdapter() { @Override public void focusLost(final FocusEvent theEvent) { updateItem(theItem, quantity); } }); sub.add(quantity); final JLabel l = new JLabel(theItem.toString()); l.setForeground(UW_PURPLE); sub.add(l); thePanel.add(sub); }

/** * Updates the set of items by changing the quantity of the specified * product to the specified quantity. * * @param theItem The product to update. * @param theQuantity The new quantity. */ private void updateItem(final Item theItem, final JTextField theQuantity) { final String text = theQuantity.getText().trim(); int number = 0; try { number = Integer.parseInt(text); if (number < 0) { // disallow negative numbers throw new NumberFormatException(); } } catch (final NumberFormatException e) { number = 0; theQuantity.setText(""); } myItems.add(new ItemOrder(theItem, number)); updateTotal(); }

/** * Updates the total displayed in the window. */ private void updateTotal() { final double total = myItems.calculateTotal().doubleValue(); myTotal.setText(NumberFormat.getCurrencyInstance().format(total)); } }

// end of class ShoppingFrame

ShoppingMain.java

/* * TCSS 305 Assignment 2 - Shopping Cart */

package view;

import java.awt.EventQueue;

import utility.FileLoader;

/** * ShoppingMain provides the main method for a simple shopping cart GUI. * * @author Marty Stepp * @author Daniel M. Zimmerman (Formatting and Comments) * @author Alan Fowler (Numerous changes including use of BigDecimal and file input) * * @version Autumn 2016 */

public final class ShoppingMain { /** * The path and name of the inventory file. */ private static final String INVENTORY_FILE = "files/tacoma.txt";

/** * A private constructor, to prevent external instantiation. */ private ShoppingMain() { }

/** * The main() method - displays and runs the shopping cart GUI. * * @param theArgs Command line arguments, ignored by this program. */ public static void main(final String... theArgs) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new ShoppingFrame(FileLoader.readItemsFromFile(INVENTORY_FILE)); } }); } // end main()

} // end class ShoppingMain

Silly Putty;4.41;6;10.04 'Java Rules!' button;0.95;10;5.00 'Java Rules!' bumper sticker;0.99;20;8.95 Computer science pen;2.00 Rubik's Cube;9.99 Mp3, Mp4, FM Music Player;18.01 Arduino Uno Ultimate Starter Kit;54.99 LEGO Mindstorms EV3;349.95 Xbox One;399.00 PlayStation 4;399.00 64 inch Plasma HDTV;1297.99

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions