001package edu.pdx.cs410J.di; 002 003import com.google.common.collect.ImmutableMap; 004import com.google.common.collect.Maps; 005import com.google.inject.Inject; 006import jakarta.xml.bind.JAXBException; 007import jakarta.xml.bind.annotation.XmlAttribute; 008import jakarta.xml.bind.annotation.XmlElement; 009import jakarta.xml.bind.annotation.XmlElementWrapper; 010import jakarta.xml.bind.annotation.XmlRootElement; 011 012import java.io.File; 013import java.io.IOException; 014import java.util.ArrayList; 015import java.util.List; 016import java.util.Map; 017 018/** 019 * Stores {@link CreditCard}s in an XML file 020 */ 021public class CreditCardDatabase extends JaxbDatabase 022{ 023 private final Map<CreditCard, Double> balances; 024 025 @Inject 026 public CreditCardDatabase(@DataDirectory File directory) throws JAXBException, IOException 027 { 028 this( directory, "CreditCards.xml"); 029 } 030 031 CreditCardDatabase( File directory, String fileName ) 032 throws IOException, JAXBException 033 { 034 super( directory, fileName, XmlCreditCardDatabase.class, XmlCreditCardDatabase.CreditCardBalance.class, CreditCard.class ); 035 036 XmlCreditCardDatabase xml = (XmlCreditCardDatabase) readFile(); 037 038 if (xml != null) { 039 this.balances = xml.getMap(); 040 } else { 041 this.balances = Maps.newHashMap(); 042 } 043 } 044 045 synchronized void setBalance(CreditCard card, double balance) { 046 this.balances.put(card, balance); 047 048 writeDatabase(); 049 } 050 051 public synchronized void debit(CreditCard card, double amount) { 052 double balance = balances.get(card); 053 balance -= amount; 054 this.balances.put(card, balance); 055 056 writeDatabase(); 057 } 058 059 private void writeDatabase() { 060 writeXml( new XmlCreditCardDatabase( this.balances) ); 061 } 062 063 public ImmutableMap<CreditCard, Double> getBalances() 064 { 065 return ImmutableMap.copyOf( this.balances ); 066 } 067 068 /** 069 * JAXB can't marshall a <code>HashMap</code>, so we need to use this stupid class to represent a CreditCard database. 070 */ 071 @XmlRootElement(name="CreditCard-database") 072 private static class XmlCreditCardDatabase 073 { 074 @XmlElementWrapper(name="CreditCards") 075 private List<CreditCardBalance> balances; 076 077 078 /** 079 * For unmarshalling 080 */ 081 public XmlCreditCardDatabase() { 082 083 } 084 085 public XmlCreditCardDatabase( Map<CreditCard, Double> inventory ) 086 { 087 balances = new ArrayList<CreditCardBalance>(inventory.size()); 088 for (Map.Entry<CreditCard, Double> count : inventory.entrySet()) { 089 balances.add(new CreditCardBalance(count.getKey(), count.getValue())); 090 } 091 } 092 093 public Map<CreditCard, Double> getMap() 094 { 095 Map<CreditCard, Double> map = Maps.newHashMap(); 096 for ( CreditCardBalance balance : balances ) { 097 map.put(balance.getCard(), balance.getBalance()); 098 } 099 return map; 100 } 101 102 @XmlRootElement(name="balance") 103 private static class CreditCardBalance 104 { 105 @XmlElement 106 private CreditCard card; 107 108 @XmlAttribute 109 private double balance; 110 111 /** 112 * For unmarshalling 113 */ 114 public CreditCardBalance() { 115 116 } 117 118 public CreditCardBalance( CreditCard card, Double balance ) 119 { 120 this.card = card; 121 this.balance = balance; 122 } 123 124 public CreditCard getCard() 125 { 126 return card; 127 } 128 129 public double getBalance() 130 { 131 return balance; 132 } 133 } 134 } 135 136}