The invoice program assumes that prices are given in dollar. Other currencies have different rules, and it makes sense to use an interface that defines the essential operations required for money values. The interface Money is given below.

There will be classes (such as Dollar and Euro) that implement this interface, but you need not know them.

In this assignment, the Product and LineItem classes have been modified to use the Money interface.

Your task is to modify the Invoice class.

Complete the following file:

Invoice.java

import java.util.ArrayList; /** Describes an invoice for a set of purchased products. */ public class Invoice { /** Constructs an invoice. @param anAddress the billing address */ public Invoice(Address anAddress) { items = new ArrayList<LineItem>(); billingAddress = anAddress; } /** Adds a charge for a product to this invoice. @param aProduct the product that the customer ordered @param quantity the quantity of the product */ public void add(Product aProduct, int quantity) { LineItem anItem = new LineItem(aProduct, quantity); items.add(anItem); } /** Formats the invoice. @return the formatted invoice */ public String format() { String r = " I N V O I C E\n\n" + billingAddress.format() + String.format("\n\n%-30s%8s%5s%8s\n", "Description", "Price", "Qty", "Total"); for (LineItem i : items) { r = r + i.format() + "\n"; } // TODO: Format amount due return r; } /** Computes the total amount due. @return the amount due */ public Money getAmountDue() { // TODO: Compute amount due } private Address billingAddress; private ArrayList<LineItem> items; }

Use the following files:

Address.java

/**
   Describes a mailing address.
*/
public class Address
{  
   /**
      Constructs a mailing address. 
      @param aName the recipient name
      @param aStreet the street
      @param aCity the city
      @param aState the two-letter state code
      @param aZip the ZIP postal code
   */
   public Address(String aName, String aStreet,
         String aCity, String aState, String aZip)
   {  
      name = aName;
      street = aStreet;
      city = aCity;
      state = aState;
      zip = aZip;
   }   

   /**
      Formats the address.
      @return the address as a string with three lines
   */
   public String format()
   {  
      return name + "\n" + street + "\n"
            + city + ", " + state + " " + zip;
   }
   
   private String name;
   private String street;
   private String city;
   private String state;
   private String zip;
}

Dollar.java

/**
   Describes an amount in dollars and cents.
*/
public class Dollar implements Money
{
   /**
      Constructs an amount in the dollar currency.
      @param dollars the number of whole dollars
      @param cents the number of cents
   */        
   public Dollar(int dollars, int cents)
   {
      this.cents = 100 * dollars + cents;
   }
   
   public void add(Money other)
   {
      assert other instanceof Dollar;
      Dollar otherDollar = (Dollar) other;
      cents += otherDollar.cents;
   }
   
   public String format()
   {
      int c = Math.abs(cents);
      String r = String.format("$%d.%02d", c / 100, c % 100);
      if (cents >= 0) return r;
      else return "(" + r + ")";
   }
   
   private int cents;
}

InvoicePrinter.java

/**
   This program demonstrates the invoice classes by printing
   a sample invoice.
*/
public class InvoicePrinter
{  
   public static void main(String[] args)
   {  
      Address samsAddress 
            = new Address("Sam's Small Appliances",
               "100 Main Street", "Anytown", "CA", "98765");

      Invoice samsInvoice = new Invoice(samsAddress);
      samsInvoice.add(new Product("Toaster", new Dollar(29, 95)), 3);
      samsInvoice.add(new Product("Hair dryer", new Dollar(24, 95)), 1);
      samsInvoice.add(new Product("Car vacuum", new Dollar(19, 99)), 2);

      System.out.println(samsInvoice.format());           
   }
}

LineItem.java

/**
   Describes a quantity of an article to purchase.
*/
public class LineItem
{  
   /**
      Constructs an item from the product and quantity.
      @param aProduct the product
      @param aQuantity the item quantity
   */
   public LineItem(Product aProduct, int aQuantity)
   {  
      theProduct = aProduct;
      quantity = aQuantity;
   }
   
   /**
      Computes the total cost of this line item.
      @return the total price
   */
   public Money getTotalPrice()
   {
      Money m = theProduct.getPrice();
      for (int i = 2; i <= quantity; i++)
         m.add(theProduct.getPrice());
      return m;
   }
   
   /**
      Formats this item.
      @return a formatted string of this item
   */
   public String format()
   {  
      return String.format("%-30s%8s%5d%8s", 
            theProduct.getDescription(), theProduct.getPrice().format(), 
            quantity, getTotalPrice().format());
   }

   private int quantity;
   private Product theProduct;
}

Money.java

/**
   This interface describes money in some currency.
*/
public interface Money
{
   /**
      Adds an amount of money to this money instance.
      @param the other money instance      
      Precondition: this amount and other belong to the same currency
   */   
   void add(Money other);
   
   /**
      Formats this money instance.
      @return a formatted string describing the value of this money instance.
   */
   String format();
}

Product.java

/**
   Describes a product with a description and a price.
*/
public class Product
{  
   /**
      Constructs a product from a description and a price.
      @param aDescription the product description
      @param aPrice the product price
   */
   public Product(String aDescription, Money aPrice)
   {  
      description = aDescription;
      price = aPrice;
   }
   
   /**
      Gets the product description.
      @return the description
   */
   public String getDescription()
   {  
      return description;
   }

   /**
      Gets the product price.
      @return the unit price
   */
   public Money getPrice()
   {
      return price;
   }
   
   private String description;
   private Money price;
}