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}