// CSVTransactionExtracter package org.javamoney.examples.ez.money.importexport; import static org.javamoney.examples.ez.money.ApplicationProperties.UI_CURRENCY_SYMBOL; import static org.javamoney.examples.ez.money.ApplicationProperties.getCSVColumnOrder; import static org.javamoney.examples.ez.money.importexport.CSVColumnKeys.AMOUNT; import static org.javamoney.examples.ez.money.importexport.CSVColumnKeys.CHECK_NUMBER; import static org.javamoney.examples.ez.money.importexport.CSVColumnKeys.DATE; import static org.javamoney.examples.ez.money.importexport.CSVColumnKeys.NOTES; import static org.javamoney.examples.ez.money.importexport.CSVColumnKeys.PAYEE; import static org.javamoney.examples.ez.money.importexport.CSVConstants.QUOTE; import static org.javamoney.examples.ez.money.importexport.CSVConstants.SEPARATOR; import static org.javamoney.examples.ez.money.model.dynamic.transaction.TransactionTypeKeys.EXPENSE; import static org.javamoney.examples.ez.money.model.dynamic.transaction.TransactionTypeKeys.INCOME; import static org.javamoney.examples.ez.money.model.dynamic.transaction.TransactionTypeKeys.TRANSFER; import static org.javamoney.examples.ez.money.utility.TransactionHelper.isExpense; import java.io.BufferedReader; import java.util.Date; import java.util.StringTokenizer; import org.javamoney.examples.ez.money.model.persisted.transaction.Transaction; import org.javamoney.moneta.Money; /** * This class facilitates extracting transactions from a CSV file. */ final class CSVTransactionExtracter extends TransactionExtracter { /** * Constructs a new transaction extractor. */ protected CSVTransactionExtracter() { setColumnOrder(getCSVColumnOrder()); } /** * This method extracts and returns the next transaction from the stream. If * there are no more transactions in the stream, then null is returned. * * @param stream * The input stream that has the transactions. * * @return The next transaction or null if there are no more transactions in * the stream. * * @throws Exception * If an error occurs. */ @Override protected Transaction next(BufferedReader stream) throws Exception { Transaction trans = null; double amount = 0.0; Date date = new Date(); String line = ""; String notes = ""; String number = ""; String payee = ""; setType(null); if ((line = stream.readLine()) != null) { StringTokenizer tokens = new StringTokenizer(line, SEPARATOR, true); int column = 0; while (tokens.hasMoreTokens() == true && column < getColumnOrder().length) { int ordinal = getColumnOrder()[column]; // Get column mapping. line = getNextToken(tokens); if (ordinal == AMOUNT.ordinal()) { amount = extractAmount(line); // Don't change the type if it is already a transfer. if (getType() == null) { if (isExpense(amount) == true) { setType(EXPENSE); } else { setType(INCOME); } } } else if (ordinal == CHECK_NUMBER.ordinal()) { number = extractCheckNumber(line); } else if (ordinal == DATE.ordinal()) { date = extractDate(line); System.out.println(date); } else if (ordinal == NOTES.ordinal()) { notes = extractNotes(line); } else if (ordinal == PAYEE.ordinal()) { // Can be either a payee or an account. if (isAccount(line) == true) { payee = extractAccount(line); setType(TRANSFER); } else { payee = extractPayee(line); } } else { // Undefined ordinal. For now it is ignored. } column += 1; } // Create the transaction and assume it is reconciled. trans = new Transaction(number, date, payee, Money.of(amount, UI_CURRENCY_SYMBOL.getCurrency()), "", notes); trans.setIsReconciled(true); } return trans; } // //////////////////////////////////////////////////////////////////////////// // Start of private methods. // //////////////////////////////////////////////////////////////////////////// private int[] getColumnOrder() { return itsColumnOrder; } private String getNextToken(StringTokenizer tokens) { String token = tokens.nextToken(); // If the next token is a token, then there was no data. if (token.equals(SEPARATOR) == true) { token = ""; } else { // This indicates the delimiter needs to be included in the field // value. if (token.startsWith(QUOTE) == true) { // The delimiter was not in the token, so remove the quotes. if (token.endsWith(QUOTE) == true) { token = token.substring(1, token.length() - 1); } else { token = token.substring(1); // Remove the first quote. // Keep appending the tokens until the last quote is found. while (tokens.hasMoreTokens() == true) { token += tokens.nextToken(); if (token.endsWith(QUOTE) == true) { break; } // Append the token that is supposed to be there. token += SEPARATOR; } // The token should end in a quote, so remove it. If not, // then the // data is invalid. if (token.endsWith(QUOTE) == true) { token = token.substring(0, token.length() - 1); } } } // The token delimiters are being returned and need to be removed // for the // next iteration. This is necessary to identify empty fields. if (tokens.hasMoreTokens() == true) { tokens.nextToken(); } } return token.trim(); } private void setColumnOrder(int[] values) { itsColumnOrder = values; } // //////////////////////////////////////////////////////////////////////////// // Start of class members. // //////////////////////////////////////////////////////////////////////////// private int[] itsColumnOrder; }