package com.skatestown.invoice; import com.skatestown.ns.invoice.InvoiceType; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import java.util.Iterator; import java.util.List; import java.io.File; /** * Check Skatestown invoice totals using JAXB */ public class InvoiceCheckerJAXB implements InvoiceChecker { /** * Check invoice totals * @param inoviceXML Invoice XML document * @exception Exception any exception returned during processing */ public void checkInvoice(File invoiceXML) throws Exception { // Create JAXB context + point it to schema types JAXBContext jc = JAXBContext.newInstance( "com.skatestown.ns.po:com.skatestown.ns.invoice"); // Create an unmarshaller Unmarshaller u = jc.createUnmarshaller(); // Unmarshall the invoice document InvoiceType inv = (InvoiceType) u.unmarshall(invoiceXML); double runningTotal = 0.0; // Iterate over items and update running total List items = inv.getOrder().getItem(); for (Iterator iter = items.iterator(); iter.hasNext(); ) { com.skatestown.ns.invoice.ItemType item = (com.skatestown.ns.invoice.ItemType) iter.next(); runningTotal += item.getQuantity() * item.getUnitPrice(); } // Add tax and shipping and handling runningTotal += inv.getShippingAndHandling(); runningTotal += inv.getTax(); // Get invoice total double total = inv.getTotalCost(); // Use delta equality to prevent cumulative binary arithmetic errors. // Choose delta = 1/2 of one cent if (Math.abs(runningTotal - total) >= .005) { throw new Exception( "Invoice error: total is " + Double.toString(total) + " while our calculation shows a total of " + Double.toString(Math.round(runningTotal * 100) / 100.0)); } } }