All Downloads are FREE. Search and download functionalities are using the official Maven repository.

expense_tally.expense_manager.transformation.ExpenseTransactionTransformer Maven / Gradle / Ivy

The newest version!
package expense_tally.expense_manager.transformation;

import expense_tally.model.persistence.database.ExpenseReport;
import expense_tally.model.persistence.transformation.ExpenseCategory;
import expense_tally.model.persistence.transformation.ExpenseManagerTransaction;
import expense_tally.model.persistence.transformation.ExpenseSubCategory;
import expense_tally.model.persistence.transformation.PaymentMethod;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A static class to provide methods for mapping {@link ExpenseReport} to {@link ExpenseManagerTransaction}.
 *
 * 

This class is an use case of the Mapper design pattern, in which the class's main purpose is to provide a set of * helpful method to map {@link ExpenseReport} into * {@link ExpenseManagerTransaction} of various forms. This implementation is inspired by * a stackoverflow answer. The deciding factor between * the design patterns of Mapper, Builder and Factory pattern is essential as things evolve, some applications are * not aware of additional attributes that needs to go under constructor where one either computes it or use default. * The critical thing is that mapper can do this for you, taken from * here.

* * @see ExpenseManagerTransaction * @see ExpenseReport */ public final class ExpenseTransactionTransformer { private static final Logger LOGGER = LogManager.getLogger(ExpenseTransactionTransformer.class); private static final String REFERENCE_AMOUNT_NUMBER_FORMAT = "[^\\d\\.]+"; private static final double ZERO_AMOUNT = 0.0; /** * Private constructor to avoid creation of object */ private ExpenseTransactionTransformer() { } /** * Return a list {@link ExpenseManagerTransaction} filtered by the transaction amount followed by the payment * method. * * @param expenseReports the list of expense reports * @return a list {@link ExpenseManagerTransaction} filtered by the transaction amount followed by the payment method. */ public static List mapExpenseReports(List expenseReports) { List mappedExpenseManagerTransactions = new ArrayList<>(); for (ExpenseReport expenseReport : expenseReports) { try { ExpenseManagerTransaction expenseManagerTransaction = mapAExpenseReport(expenseReport); mappedExpenseManagerTransactions.add(expenseManagerTransaction); } catch (RuntimeException runtimeException) { LOGGER.atWarn() .withThrowable(runtimeException) .log("Unable to parse expense report entry. expenseReport={}", expenseReport); } } return mappedExpenseManagerTransactions; } public static Map>> convertToTableOfAmountAndPaymentMethod( List expenseManagerTransactions) { Map>> expensesByAmountAndPaymentMethod = new HashMap<>(); expenseManagerTransactions.forEach(expenseManagerTransaction -> { Double transactionAmount = (expenseManagerTransaction.getReferenceAmount() > 0) ? expenseManagerTransaction.getReferenceAmount() : expenseManagerTransaction.getAmount(); PaymentMethod paymentMethod = expenseManagerTransaction.getPaymentMethod(); Map> expenseTransactionsByPaymentMethod = expensesByAmountAndPaymentMethod.computeIfAbsent(transactionAmount, k -> new HashMap<>()); List expenseManagerTransactionList = expenseTransactionsByPaymentMethod.computeIfAbsent(paymentMethod, k -> new ArrayList<>()); expenseManagerTransactionList.add(expenseManagerTransaction); }); return expensesByAmountAndPaymentMethod; } /** * Return a {@link ExpenseManagerTransaction} mapped from a {@link ExpenseReport} * * @param expenseReport the {@link ExpenseReport} to be mapped * @return the mapped {@link ExpenseManagerTransaction} */ private static ExpenseManagerTransaction mapAExpenseReport(ExpenseReport expenseReport) { int id = expenseReport.getId(); String amountString = expenseReport.getAmount(); double amount = Double.parseDouble(amountString); String expenseCategoryString = expenseReport.getCategory(); ExpenseCategory expenseCategory = ExpenseCategory.resolve(expenseCategoryString); String expenseCategorySubcategoryString = expenseReport.getSubcategory(); ExpenseSubCategory expenseSubCategory = ExpenseSubCategory.resolve(expenseCategorySubcategoryString); String description = expenseReport.getDescription(); long expendedTimeInSecondSinceEpoch = expenseReport.getExpensedTime(); Instant expendedTime = Instant.ofEpochMilli(expendedTimeInSecondSinceEpoch); //This time is in UTC String paymentMethodString = expenseReport.getPaymentMethod(); PaymentMethod paymentMethod = PaymentMethod.resolve(paymentMethodString); ExpenseManagerTransaction expenseManagerTransaction = ExpenseManagerTransaction.create(id, amount, expenseCategory, expenseSubCategory, paymentMethod, description, expendedTime); String referenceNumber = expenseReport.getReferenceNumber(); double referenceAmount = (referenceNumber.isBlank()) ? ZERO_AMOUNT : parseReferenceAmount(referenceNumber); expenseManagerTransaction.setReferenceAmount(referenceAmount); return expenseManagerTransaction; } private static double parseReferenceAmount(final String referenceAmountString) { String cleansedReferenceAmountString = referenceAmountString.replaceAll(REFERENCE_AMOUNT_NUMBER_FORMAT, StringUtils.EMPTY); double referenceAmount = Double.parseDouble(cleansedReferenceAmountString); LOGGER.atTrace().log("Converted a reference amount string {} to {}", referenceAmountString, referenceAmount); return referenceAmount; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy