org.pau.assetmanager.viewmodel.chart.ChartDataModel.java Source code

Java tutorial

Introduction

Here is the source code for org.pau.assetmanager.viewmodel.chart.ChartDataModel.java

Source

/**
 * This file is part of Pau's Asset Manager Project.
 *
 * Pau's Asset Manager Project is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Pau's Asset Manager Project is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Pau's Asset Manager Project.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.pau.assetmanager.viewmodel.chart;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.pau.assetmanager.entities.Annotation;
import org.pau.assetmanager.entities.Book;
import org.pau.assetmanager.entities.ExpensesAnnotation;
import org.pau.assetmanager.entities.GeneralExpensesAnnotation;
import org.pau.assetmanager.entities.GeneralIncomeAnnotation;
import org.pau.assetmanager.entities.IncomeAnnotation;
import org.pau.assetmanager.entities.MovementExpensesAnnotation;
import org.pau.assetmanager.entities.MovementIncomeAnnotation;
import org.pau.assetmanager.entities.PropertyBook;
import org.pau.assetmanager.entities.PropertyExpensesAnnotation;
import org.pau.assetmanager.entities.PropertyIncomeAnnotation;
import org.pau.assetmanager.entities.StockExpensesAnnotation;
import org.pau.assetmanager.entities.StockIncomeAnnotation;
import org.pau.assetmanager.entities.StocksBook;
import org.pau.assetmanager.viewmodel.stocks.HistoricalStockBalanceState;
import org.pau.assetmanager.viewmodel.stocks.StockConceptPerformance;
import org.pau.assetmanager.viewmodel.stocks.StockState;
import org.pau.assetmanager.viewmodel.type.BookSelectionType;
import org.pau.assetmanager.viewmodel.utils.BookSelection;
import org.pau.assetmanager.viewmodel.utils.ProperitesChartDataModel;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Table;

/**
 * This class is a factory of data models that are used by the charts
 * 
 * @author Pau Carr Cardona
 * 
 */

public class ChartDataModel {

    public static final String INCOME_STOCKS = "Ingresos en bolsa";
    public static final String EXPENSES_STOCKS = "Gastos en bolsa";
    public static final String INCOME_OWN = "Ingresos generales";
    public static final String EXPENSES_OWN = "Gastos generales";
    public static final String INCOME_PROPERTIES = "Ingresos de propiedades";
    public static final String EXPENSES_PROPERITES = "Gastos de propiedades";
    public static final String INCOME_MOVEMENT = "Ingresos de movimientos";
    public static final String EXPENSES_MOVEMENT = "Gastos de movimientos";
    public static final String INCOME = "Ingresos";
    public static final String EXPENSES = "Gastos";
    public static final String TOTAL = "Total Mensual";
    public static final String TOTAL_CUMULATIVE = "Total Acumulado";
    public static final String TOTAL_CUMULATIVE_STOCKS_PURCHASED = "Capital latente de acciones compradas";
    public static final String TOTAL_CUMULATIVE_STOCKS_COMBINED = "Beneficios o pedidas en acciones compradas";
    public static final String HACIENDA = "Hacienda";

    /**
     * @param expensesDataForBook
     *            expenses concept to amount map
     * @return the pie chart data model
     */
    public static PieDataset expensesPieChartDataset(Map<String, Double> expensesDataForBook) {
        DefaultPieDataset dataset = new DefaultPieDataset();
        Double total = 0.0;
        for (String concept : expensesDataForBook.keySet()) {
            total += expensesDataForBook.get(concept);
        }
        Double otros = 0.0;
        for (String concept : expensesDataForBook.keySet()) {
            Double value = expensesDataForBook.get(concept);
            if (value / total > 0.01) {
                dataset.setValue(concept, expensesDataForBook.get(concept));
            } else {
                otros += expensesDataForBook.get(concept);
            }
        }
        if (otros > 0.0) {
            dataset.setValue("Gastos que representan menos de un 1%", otros);
        }
        return dataset;
    }

    /**
     * Returns the graph model of a grouping bar for each month along a year.
     * Each monthly group contains a bar that represent the totals for each of
     * the selected properties (Incomes - Expenses) The selected property will
     * be the one from the properties book or all the properties for a client in
     * case the selection is for all the books
     * 
     * @return the grouping bar model
     */
    public static DefaultCategoryDataset getTotalsOverTimePerBook(List<Annotation> annotations, int year,
            Book selectedBook, List<PropertyBook> listOfProperties) {

        ProperitesChartDataModel properitesChartDataModel = getTotalsPerBookChartDataModel(annotations, year,
                listOfProperties);

        List<String> listOfLabels = getListOfMonthTimeLabelsForYear(year);

        DefaultCategoryDataset model = new DefaultCategoryDataset();

        for (String bookName : properitesChartDataModel.getChartData().keySet()) {
            Map<String, Double> valuesMapHacienda = properitesChartDataModel.getChartData().get(bookName);
            for (String currentLabel : listOfLabels) {
                Double currentValue = valuesMapHacienda.get(currentLabel);
                model.addValue(currentValue, bookName, currentLabel);
            }
        }

        return model;
    }

    private static Double getYearBeforeFinalVirtualStockBalance(Integer year,
            Table<Integer, Integer, Set<StockState>> historicalStockBalanceStateTable) {
        Double balance = 0.0;
        final Integer yearBefore = year - 1;
        Map<Integer, Map<Integer, Set<StockState>>> historicalStockBalanceStateRowMap = historicalStockBalanceStateTable
                .rowMap();
        historicalStockBalanceStateRowMap = Maps.filterKeys(historicalStockBalanceStateRowMap,
                new Predicate<Integer>() {
                    @Override
                    public boolean apply(Integer year) {
                        return year <= yearBefore;
                    }
                });
        List<Integer> years = Lists.newArrayList(historicalStockBalanceStateRowMap.keySet());
        if (years.size() > 0) {
            Collections.sort(years);
            // get last year
            Integer lastYear = years.get(years.size() - 1);
            Map<Integer, Set<StockState>> historicalStockBalanceStateLastYear = historicalStockBalanceStateRowMap
                    .get(lastYear);
            List<Integer> months = Lists.newArrayList(historicalStockBalanceStateLastYear.keySet());
            Collections.sort(months);
            Integer lastMonth = months.get(months.size() - 1);
            Set<StockState> historicalStockLastMonth = historicalStockBalanceStateLastYear.get(lastMonth);
            for (StockState currentStockState : historicalStockLastMonth) {
                balance += currentStockState.getVirtualBalance();
            }
        }
        return balance;
    }

    /**
     * Returns the total balance along one year in a monthly basis.
     * 
     * @param year
     *            the balance
     * @param yearToAnnotationMultimap
     *            year --> annotations multimap
     * @param selectedBook
     *            book selected for the balance
     * @param bookSelectionType
     *            type of book
     * @return
     */
    public static DefaultCategoryDataset getBalance(Integer year,
            Multimap<Integer, Annotation> yearToAnnotationMultimap, BookSelection bookSelection,
            Boolean includePurchasedStocks, Optional<String> optionalStockLabel) {
        Book selectedBook = bookSelection.getSelectedBook();
        Double previousYearsTotals = 0.0;
        for (Integer currentYear : yearToAnnotationMultimap.keySet()) {
            if (currentYear < year) {
                for (Annotation currentAnnotation : yearToAnnotationMultimap.get(currentYear)) {
                    previousYearsTotals += currentAnnotation.getSignedAmount();
                }
            }
        }
        Set<StocksBook> stockBooks = new HashSet<StocksBook>();
        Map<String, Double> totalData = new HashMap<String, Double>();
        for (int month = 0; month < 12; month++) {
            Calendar currentcalendar = GregorianCalendar.getInstance();
            currentcalendar.set(Calendar.MONTH, month);
            currentcalendar.set(Calendar.YEAR, year);
            currentcalendar.set(Calendar.DAY_OF_MONTH, 1);
            String mainLabel = getTimeLabel(currentcalendar.getTime());
            totalData.put(mainLabel, 0.0);
            Collection<Annotation> annotations = yearToAnnotationMultimap.get(year);
            if (annotations != null) {
                for (Annotation annotation : annotations) {
                    String currentAnnotationLabel = getTimeLabel(annotation.getDate());
                    if (currentAnnotationLabel.equals(mainLabel)) {
                        if (annotation.getBook() instanceof StocksBook) {
                            stockBooks.add((StocksBook) annotation.getBook());
                        }
                        totalData.put(mainLabel, totalData.get(mainLabel) + annotation.getSignedAmount());
                    }
                }
            }
        }

        DefaultCategoryDataset model = new DefaultCategoryDataset();
        List<String> listOfLabels = getListOfMonthTimeLabelsForYear(year);

        Map<String, Double> labelToToalCumulativeMap = new HashMap<String, Double>();

        Double total = 0.0;
        for (String currentLabel : listOfLabels) {
            Double currentValue = totalData.get(currentLabel);
            if (currentValue != null) {
                total += currentValue;
            }
            labelToToalCumulativeMap.put(currentLabel, total + previousYearsTotals);
        }

        for (String currentLabel : listOfLabels) {
            model.addValue(labelToToalCumulativeMap.get(currentLabel), TOTAL_CUMULATIVE, currentLabel);
        }

        // add stock information in case it is necessary
        if ((selectedBook instanceof StocksBook) && includePurchasedStocks) {
            Table<Integer, Integer, Set<StockState>> historicalStockBalanceStateTable = HistoricalStockBalanceState
                    .getConiniousHistoricalStockBalanceStateTable(bookSelection, year, optionalStockLabel);
            Collection<Annotation> annotationsForYear = yearToAnnotationMultimap.get(year);
            if (annotationsForYear == null) {
                annotationsForYear = Lists.newLinkedList();
            }
            Collection<Annotation> movementAnnotationsForYear = Collections2.filter(annotationsForYear,
                    new Predicate<Annotation>() {
                        @Override
                        public boolean apply(Annotation input) {
                            return input instanceof MovementExpensesAnnotation
                                    || input instanceof MovementIncomeAnnotation;
                        }
                    });
            movementAnnotationsForYear = Collections2.filter(movementAnnotationsForYear,
                    new Predicate<Annotation>() {
                        @Override
                        public boolean apply(Annotation input) {
                            return input instanceof MovementExpensesAnnotation
                                    || input instanceof MovementIncomeAnnotation;
                        }
                    });
            final Calendar currentcalendar = GregorianCalendar.getInstance();
            Multimap<Integer, Annotation> monthToAnnotationMultimap = Multimaps.index(movementAnnotationsForYear,
                    new Function<Annotation, Integer>() {
                        @Override
                        public Integer apply(Annotation input) {
                            currentcalendar.setTime(input.getDate());
                            return currentcalendar.get(Calendar.MONTH);
                        }
                    });

            Double movementBalance = getAllPreviousMovementCumulative(yearToAnnotationMultimap, year);
            if (historicalStockBalanceStateTable != null) {
                Map<Integer, Set<StockState>> historyForYear = historicalStockBalanceStateTable.rowMap().get(year);
                for (Integer currentMonth = 0; currentMonth <= 11; currentMonth++) {
                    Double balance = 0.0;
                    if (historyForYear != null && historyForYear.get(currentMonth) != null) {
                        for (StockState currentStockState : historyForYear.get(currentMonth)) {
                            balance += currentStockState.getVirtualBalanceForForcedYearAndMonth(year, currentMonth);
                        }
                    } else {
                        balance = getYearBeforeFinalVirtualStockBalance(year, historicalStockBalanceStateTable);
                    }
                    if (monthToAnnotationMultimap.get(currentMonth) != null) {
                        for (Annotation movementAnnotation : monthToAnnotationMultimap.get(currentMonth)) {
                            movementBalance += movementAnnotation.getSignedAmount();
                        }
                    }
                    model.addValue(balance, TOTAL_CUMULATIVE_STOCKS_PURCHASED, listOfLabels.get(currentMonth));
                    Double cumulativeBalance = labelToToalCumulativeMap.get(listOfLabels.get(currentMonth));

                    model.addValue(balance + cumulativeBalance - movementBalance, TOTAL_CUMULATIVE_STOCKS_COMBINED,
                            listOfLabels.get(currentMonth));
                }

            }
        }

        return model;
    }

    private static Double getAllPreviousMovementCumulative(Multimap<Integer, Annotation> yearToAnnotationMultimap,
            Integer year) {
        List<Integer> listOfYears = Lists.newLinkedList(yearToAnnotationMultimap.keys());
        if (listOfYears.size() == 0) {
            return 0.0;
        }
        Collections.sort(listOfYears);
        double allPreviousMovementCumulative = 0.0;
        for (int currentYearIndex = 0; currentYearIndex < listOfYears.size()
                && listOfYears.get(currentYearIndex) < year; currentYearIndex++) {
            for (Annotation annotation : yearToAnnotationMultimap.get(listOfYears.get(currentYearIndex))) {
                allPreviousMovementCumulative += annotation.getSignedAmount();
            }

        }
        return allPreviousMovementCumulative;
    }

    /**
     * Generates chart model of a time series in which there are four series --
     * Income: the sum of amount of income annotations for a given month in a
     * year -- Expenses: the sum of amount of expenses annotations for a given
     * month in a year -- Monthly Total: the *difference* between Income and
     * Expenses (Monthly Total := Income - Expenses) -- Cumulative: the
     * cumulative sum over time of 'Monthly Total'
     * 
     * @return the chart model
     */
    public static DefaultCategoryDataset getIncomeExpensesSimpleOverTime(List<Annotation> annotations, int year,
            Book selectedBook) {

        ProperitesChartDataModel properitesChartDataModel = getIncomeExpensesOverTimeChartDataModel(annotations,
                year);

        List<String> listOfLabels = getListOfMonthTimeLabelsForYear(year);

        DefaultCategoryDataset model = new DefaultCategoryDataset();

        Map<String, Double> valuesMapIncome = properitesChartDataModel.getChartData().get(INCOME_PROPERTIES);
        Map<String, Double> valuesMapIncomeOwn = properitesChartDataModel.getChartData().get(INCOME_OWN);
        Map<String, Double> valuesMapIncomeStocks = properitesChartDataModel.getChartData().get(INCOME_STOCKS);
        Map<String, Double> valuesMapIncomeMovement = properitesChartDataModel.getChartData().get(INCOME_MOVEMENT);
        for (String currentLabel : listOfLabels) {
            Double currentValue = valuesMapIncome.get(currentLabel);
            Double currentValueOwn = valuesMapIncomeOwn.get(currentLabel);
            Double currentValueStocks = valuesMapIncomeStocks.get(currentLabel);
            Double currentValueMovement = valuesMapIncomeMovement.get(currentLabel);
            model.addValue(currentValueMovement + currentValue + currentValueOwn + currentValueStocks, INCOME,
                    currentLabel);
        }

        Map<String, Double> valuesMapExpenses = properitesChartDataModel.getChartData().get(EXPENSES_PROPERITES);
        Map<String, Double> valuesMapExpensesOwn = properitesChartDataModel.getChartData().get(EXPENSES_OWN);
        Map<String, Double> valuesMapExpensesStocks = properitesChartDataModel.getChartData().get(EXPENSES_STOCKS);
        Map<String, Double> valuesMapExpensesMovement = properitesChartDataModel.getChartData()
                .get(EXPENSES_MOVEMENT);
        for (String currentLabel : listOfLabels) {
            Double currentValue = valuesMapExpenses.get(currentLabel);
            Double currentValueOwn = valuesMapExpensesOwn.get(currentLabel);
            Double currentValueStocks = valuesMapExpensesStocks.get(currentLabel);
            Double currentValueMovement = valuesMapExpensesMovement.get(currentLabel);
            model.addValue(currentValueMovement + currentValue + currentValueOwn + currentValueStocks, EXPENSES,
                    currentLabel);
        }

        Map<String, Double> valuesMap = properitesChartDataModel.getChartData().get(TOTAL);
        for (String currentLabel : listOfLabels) {
            Double currentValue = valuesMap.get(currentLabel);
            model.addValue(currentValue, TOTAL, currentLabel);
        }

        Double total = 0.0;
        for (String currentLabel : listOfLabels) {
            Double currentValue = valuesMap.get(currentLabel);
            if (currentValue != null) {
                total += currentValue;
            }
            model.addValue(total, TOTAL_CUMULATIVE, currentLabel);
        }

        return model;
    }

    /**
     * Generates the image of a grouping bar for each month along a year. Each
     * monthly group contains two bars (Income and Expenses) for each of the
     * three types of books type (General, Stocks and Properties)
     * 
     * @return the chart model
     */
    public static DefaultCategoryDataset getIncomeExpensesOverTime(List<Annotation> annotations, int year,
            Book selectedBook, BookSelectionType bookSelectionType) {

        ProperitesChartDataModel properitesChartDataModel = getIncomeExpensesOverTimeChartDataModel(annotations,
                year);

        List<String> listOfLabels = getListOfMonthTimeLabelsForYear(year);

        DefaultCategoryDataset model = new DefaultCategoryDataset();

        if (bookSelectionType.getIsAllBooks() || (selectedBook instanceof PropertyBook)) {
            Map<String, Double> valuesMapIncome = properitesChartDataModel.getChartData().get(INCOME_PROPERTIES);
            for (String currentLabel : listOfLabels) {
                Double currentValue = valuesMapIncome.get(currentLabel);
                model.addValue(currentValue, INCOME_PROPERTIES, currentLabel);
            }
        }

        if (bookSelectionType.getIsAllBooks() || !(selectedBook instanceof PropertyBook)) {
            Map<String, Double> valuesMapIncomeOwn = properitesChartDataModel.getChartData().get(INCOME_OWN);
            for (String currentLabel : listOfLabels) {
                Double currentValue = valuesMapIncomeOwn.get(currentLabel);
                model.addValue(currentValue, INCOME_OWN, currentLabel);
            }
        }

        if (bookSelectionType.getIsAllBooks() || !(selectedBook instanceof PropertyBook)) {
            Map<String, Double> valuesMapIncomeStocks = properitesChartDataModel.getChartData().get(INCOME_STOCKS);
            for (String currentLabel : listOfLabels) {
                Double currentValue = valuesMapIncomeStocks.get(currentLabel);
                model.addValue(currentValue, INCOME_STOCKS, currentLabel);
            }
        }

        if (bookSelectionType.getIsAllBooks() || (selectedBook instanceof PropertyBook)) {
            Map<String, Double> valuesMapExpenses = properitesChartDataModel.getChartData()
                    .get(EXPENSES_PROPERITES);
            for (String currentLabel : listOfLabels) {
                Double currentValue = valuesMapExpenses.get(currentLabel);
                model.addValue(currentValue, EXPENSES_PROPERITES, currentLabel);
            }
        }

        if (bookSelectionType.getIsAllBooks() || !(selectedBook instanceof PropertyBook)) {
            Map<String, Double> valuesMapExpensesOwn = properitesChartDataModel.getChartData().get(EXPENSES_OWN);
            for (String currentLabel : listOfLabels) {
                Double currentValue = valuesMapExpensesOwn.get(currentLabel);
                model.addValue(currentValue, EXPENSES_OWN, currentLabel);
            }
        }

        if (bookSelectionType.getIsAllBooks() || !(selectedBook instanceof PropertyBook)) {
            Map<String, Double> valuesMapExpensesStocks = properitesChartDataModel.getChartData()
                    .get(EXPENSES_STOCKS);
            for (String currentLabel : listOfLabels) {
                Double currentValue = valuesMapExpensesStocks.get(currentLabel);
                model.addValue(currentValue, EXPENSES_STOCKS, currentLabel);
            }
        }

        if (!bookSelectionType.getIsAllBooks()) {

            Map<String, Double> valuesMap = properitesChartDataModel.getChartData().get(TOTAL);
            for (String currentLabel : listOfLabels) {
                Double currentValue = valuesMap.get(currentLabel);
                model.addValue(currentValue, TOTAL, currentLabel);
            }

            Double total = 0.0;
            for (String currentLabel : listOfLabels) {
                Double currentValue = valuesMap.get(currentLabel);
                if (currentValue != null) {
                    total += currentValue;
                }
                model.addValue(total, TOTAL_CUMULATIVE, currentLabel);
            }
        }
        return model;
    }

    /**
     * @param year
     *            of the list
     * @return the list of labels that represent a month in a year
     */
    private static List<String> getListOfMonthTimeLabelsForYear(int year) {
        List<String> listOfLabels = new LinkedList<String>();
        for (int month = 0; month < 12; month++) {
            Calendar currentcalendar = GregorianCalendar.getInstance();
            currentcalendar.set(Calendar.MONTH, month);
            currentcalendar.set(Calendar.YEAR, year);
            currentcalendar.set(Calendar.DAY_OF_MONTH, 1);
            String mainLabel = getTimeLabel(currentcalendar.getTime());
            listOfLabels.add(mainLabel);
        }
        return listOfLabels;
    }

    /**
     * @param annotations
     *            annotations to use
     * @param year
     *            the year for the annotations
     * @return The data model of a grouping bar for each month along a year.
     *         Each monthly group contains two bars (Income and Expenses) for
     *         each of the three types of books type (General, Stocks and
     *         Properties)
     */
    private static ProperitesChartDataModel getIncomeExpensesOverTimeChartDataModel(List<Annotation> annotations,
            int year) {
        Map<String, Double> incomeData = new HashMap<String, Double>();
        Map<String, Double> expensesData = new HashMap<String, Double>();
        Map<String, Double> incomeDataStocks = new HashMap<String, Double>();
        Map<String, Double> expensesDataStocks = new HashMap<String, Double>();
        Map<String, Double> incomeDataOwn = new HashMap<String, Double>();
        Map<String, Double> expensesDataOwn = new HashMap<String, Double>();
        Map<String, Double> incomeDataMovement = new HashMap<String, Double>();
        Map<String, Double> expensesDataMovement = new HashMap<String, Double>();
        Map<String, Double> totalData = new HashMap<String, Double>();
        for (int month = 0; month < 12; month++) {
            Calendar currentcalendar = GregorianCalendar.getInstance();
            currentcalendar.set(Calendar.MONTH, month);
            currentcalendar.set(Calendar.YEAR, year);
            currentcalendar.set(Calendar.DAY_OF_MONTH, 1);
            String mainLabel = getTimeLabel(currentcalendar.getTime());
            incomeDataOwn.put(mainLabel, 0.0);
            expensesDataOwn.put(mainLabel, 0.0);
            incomeDataMovement.put(mainLabel, 0.0);
            expensesDataMovement.put(mainLabel, 0.0);
            incomeData.put(mainLabel, 0.0);
            expensesData.put(mainLabel, 0.0);
            incomeDataStocks.put(mainLabel, 0.0);
            expensesDataStocks.put(mainLabel, 0.0);
            totalData.put(mainLabel, 0.0);
            for (Annotation annotation : annotations) {
                String currentAnnotationLabel = getTimeLabel(annotation.getDate());
                if (currentAnnotationLabel.equals(mainLabel)) {
                    if (annotation instanceof ExpensesAnnotation) {
                        if (annotation instanceof PropertyExpensesAnnotation) {
                            expensesData.put(mainLabel, expensesData.get(mainLabel) + annotation.getSignedAmount());
                        } else if (annotation instanceof StockExpensesAnnotation) {
                            expensesDataStocks.put(mainLabel,
                                    expensesDataStocks.get(mainLabel) + annotation.getSignedAmount());
                        } else if (annotation instanceof GeneralExpensesAnnotation) {
                            expensesDataOwn.put(mainLabel,
                                    expensesDataOwn.get(mainLabel) + annotation.getSignedAmount());
                        } else if (annotation instanceof MovementExpensesAnnotation) {
                            expensesDataMovement.put(mainLabel,
                                    expensesDataMovement.get(mainLabel) + annotation.getSignedAmount());
                        }
                        totalData.put(mainLabel, totalData.get(mainLabel) + annotation.getSignedAmount());
                    } else if (annotation instanceof IncomeAnnotation) {
                        if (annotation instanceof PropertyIncomeAnnotation) {
                            incomeData.put(mainLabel, incomeData.get(mainLabel) + annotation.getSignedAmount());
                        } else if (annotation instanceof StockIncomeAnnotation) {
                            incomeDataStocks.put(mainLabel,
                                    incomeDataStocks.get(mainLabel) + annotation.getSignedAmount());
                        } else if (annotation instanceof GeneralIncomeAnnotation) {
                            incomeDataOwn.put(mainLabel,
                                    incomeDataOwn.get(mainLabel) + annotation.getSignedAmount());
                        } else if (annotation instanceof MovementIncomeAnnotation) {
                            incomeDataMovement.put(mainLabel,
                                    incomeDataMovement.get(mainLabel) + annotation.getSignedAmount());
                        }
                        totalData.put(mainLabel, totalData.get(mainLabel) + annotation.getSignedAmount());
                    }
                }
            }
        }
        ProperitesChartDataModel properitesChartDataModel = new ProperitesChartDataModel();
        Map<String, Map<String, Double>> chartData = properitesChartDataModel.getChartData();
        chartData.put(INCOME_STOCKS, incomeDataStocks);
        chartData.put(EXPENSES_STOCKS, expensesDataStocks);
        chartData.put(INCOME_OWN, incomeDataOwn);
        chartData.put(EXPENSES_OWN, expensesDataOwn);
        chartData.put(INCOME_MOVEMENT, incomeDataMovement);
        chartData.put(EXPENSES_MOVEMENT, expensesDataMovement);
        chartData.put(INCOME_PROPERTIES, incomeData);
        chartData.put(EXPENSES_PROPERITES, expensesData);
        chartData.put(TOTAL, totalData);
        return properitesChartDataModel;
    }

    /**
     * Returns the graph model of a grouping bar for each month along a year.
     * Each monthly group contains a bar that represent the totals for each of
     * the selected properties (Incomes - Expenses) The selected property will
     * be the one from the properties book or all the properties for a client in
     * case the selection is for all the books
     * 
     * @return the grouping bar model
     */
    private static ProperitesChartDataModel getTotalsPerBookChartDataModel(List<Annotation> annotations, int year,
            List<PropertyBook> listOfProperties) {
        ProperitesChartDataModel properitesChartDataModel = new ProperitesChartDataModel();
        Map<String, Map<String, Double>> chartData = properitesChartDataModel.getChartData();
        for (Book book : listOfProperties) {
            Map<String, Double> currentBookData = new HashMap<String, Double>();
            chartData.put(book.getName(), currentBookData);
            for (int month = 0; month < 12; month++) {
                Calendar currentcalendar = GregorianCalendar.getInstance();
                currentcalendar.set(Calendar.MONTH, month);
                currentcalendar.set(Calendar.YEAR, year);
                currentcalendar.set(Calendar.DAY_OF_MONTH, 1);
                String mainLabel = getTimeLabel(currentcalendar.getTime());
                currentBookData.put(mainLabel, 0.0);
                for (Annotation annotation : annotations) {
                    if (annotation.getBook().getName().equals(book.getName())) {
                        String currentAnnotationLabel = getTimeLabel(annotation.getDate());
                        if (currentAnnotationLabel.equals(mainLabel)) {
                            currentBookData.put(mainLabel,
                                    currentBookData.get(mainLabel) + annotation.getSignedAmount());
                        }
                    }
                }
            }
        }
        return properitesChartDataModel;
    }

    /**
     * @param date
     * @return the month time label
     */
    private static String getTimeLabel(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMM-yyyy");
        return simpleDateFormat.format(date);
    }

    /**
     * Generates the chart model of a pie chart that displays the percentage of
     * expenses of the different books which for a given year are loosing money
     * (not profitable)
     * 
     * @return the database model
     */
    public static PieDataset deficitsPieChartDataset(List<Annotation> anotations) {
        Map<String, Double> incomeForBook = new HashMap<String, Double>();
        for (Annotation annotation : anotations) {
            String name = annotation.getBook().getName();
            if (!incomeForBook.containsKey(name)) {
                incomeForBook.put(name, 0.0);
            }
            incomeForBook.put(name, incomeForBook.get(name) - annotation.getSignedAmount());
        }
        List<String> keysToRemove = new LinkedList<String>();
        for (String name : incomeForBook.keySet()) {
            Double value = incomeForBook.get(name);
            if (value < 0.0) {
                keysToRemove.add(name);
            }
        }
        for (String addres : keysToRemove) {
            incomeForBook.remove(addres);
        }
        DefaultPieDataset dataset = new DefaultPieDataset();
        for (String name : incomeForBook.keySet()) {
            dataset.setValue(name, incomeForBook.get(name));
        }
        return dataset;
    }

    /**
     * Generates the a chart model of a pie chart that displays the percentage
     * of income of the different books which for a given year are profitable
     * 
     * @return the char model
     */
    public static PieDataset incomesPieChartDataset(List<Annotation> anotations) {
        Map<String, Double> incomeForBook = new HashMap<String, Double>();
        for (Annotation annotation : anotations) {
            String name = annotation.getBook().getName();
            if (!incomeForBook.containsKey(name)) {
                incomeForBook.put(name, 0.0);
            }
            incomeForBook.put(name, incomeForBook.get(name) + annotation.getSignedAmount());
        }
        List<String> keysToRemove = new LinkedList<String>();
        for (String name : incomeForBook.keySet()) {
            Double value = incomeForBook.get(name);
            if (value < 0.0) {
                keysToRemove.add(name);
            }
        }
        for (String addres : keysToRemove) {
            incomeForBook.remove(addres);
        }
        DefaultPieDataset dataset = new DefaultPieDataset();
        for (String name : incomeForBook.keySet()) {
            dataset.setValue(name, incomeForBook.get(name));
        }
        return dataset;
    }

    /**
     * Generates a chart model of a chart with the performance of the sold
     * stocks. It computes the amount of money earned or lost given the price
     * per stock of the sold stocks.
     * 
     * Note: The chart has into account that the stocks could have been bought
     * at different points in time and that the sold stocks can span different
     * different 'stock purchases' with different price per stock
     * 
     * @return the chart model
     */
    public static CategoryDataset getStockConceptsPerformance(
            Map<String, StockConceptPerformance> stocksConceptToProfitLimitedToNumberOfSoldSlocks) {
        DefaultCategoryDataset model = new DefaultCategoryDataset();

        for (String concept : stocksConceptToProfitLimitedToNumberOfSoldSlocks.keySet()) {
            StockConceptPerformance stockConceptPerformance = stocksConceptToProfitLimitedToNumberOfSoldSlocks
                    .get(concept);
            model.addValue(stockConceptPerformance.getProfit(), concept, stockConceptPerformance);
        }
        return model;
    }

}