investiagenofx2.view.InvestiaGenOFXController.java Source code

Java tutorial

Introduction

Here is the source code for investiagenofx2.view.InvestiaGenOFXController.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package investiagenofx2.view;

import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlHeading4;
import com.gargoylesoftware.htmlunit.html.HtmlHeading5;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSection;
import com.gargoylesoftware.htmlunit.html.HtmlPasswordInput;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTable;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import investiagenofx2.InvestiaGenOFX;
import investiagenofx2.model.Account;
import investiagenofx2.model.Investment;
import investiagenofx2.model.Transaction;
import investiagenofx2.util.MyOwnException;
import investiagenofx2.util.OFXUtilites;
import investiagenofx2.util.PropertiesInit;
import investiagenofx2.util.Utilities;

import java.io.File;
import java.io.IOException;

import java.net.URL;
import java.time.LocalDate;
import java.util.ArrayList;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import ofx.OFX;
import org.apache.commons.lang3.StringUtils;

import static org.apache.commons.lang3.text.WordUtils.capitalizeFully;

/**
 * FXML Controller class
 *
 * @author Pierre
 */
public class InvestiaGenOFXController implements Initializable {

    private static final int[] linkAccountToLocalAccountIndex = new int[25];
    private static HtmlPage htmlPage;
    private static ArrayList<Account> accounts;
    private static String accountOwnerName;
    private static LocalDate dataAsDate;
    private static ObservableList<Investment> investments;
    @FXML
    private TextField txt_investiaURL;
    @FXML
    private ComboBox<String> cbo_clientNum;
    @FXML
    private PasswordField psw_password;
    @FXML
    private Button btn_login;
    @FXML
    private Button btn_logout;
    @FXML
    private Button btn_accounts;
    @FXML
    private Button btn_summary;
    @FXML
    private ComboBox<String> cbo_accounts;
    @FXML
    private DatePicker dtp_lastDate;
    @FXML
    private MenuItem mnu_quitter;
    @FXML
    private Label lbl_ownername;
    @FXML
    private Label lbl_message;

    public static void addAccount(Account account) {
        accounts.add(account);
        int localAccountIndex = accounts.size() - 1;
        int linkAccountIndex = PropertiesInit.getLinkAccountIndex(accountOwnerName.split(" ")[0] + "\\"
                + account.getAccountType() + "\\" + account.getAccountProvider());
        linkAccountToLocalAccountIndex[linkAccountIndex] = localAccountIndex;
    }

    private static String genOFXFile(ArrayList<Account> accounts) throws MyOwnException {
        OFXUtilites.setCurrency("CAD");
        OFXUtilites.setIntubid("04297");
        OFX ofx = new OFX();
        ofx.setSIGNONMSGSRSV1(OFXUtilites
                .genSignonResponseMessageSet(dataAsDate.format(Utilities.myDateFormat()) + "100000", "Investia"));
        ofx.setINVSTMTMSGSRSV1(OFXUtilites.genTransacInvestmentStatementResponseMessageSet(accounts));
        ofx.setSECLISTMSGSRSV1(OFXUtilites.genSecurityListResponseMessageSet(accounts));
        String fileName;
        if (accounts.size() > 1) {
            fileName = "Investia-" + accountOwnerName.split(" ")[0] + "TousLesComptes-"
                    + dataAsDate.format(Utilities.myDateFormat()) + ".qfx";
        } else {
            fileName = "Investia-" + accounts.get(0).getAccountID() + "-"
                    + dataAsDate.format(Utilities.myDateFormat()) + ".qfx";
        }
        Utilities.genOFXFile(ofx, fileName);
        return fileName;
    }

    /**
     * @return the investments
     */
    public static ObservableList<Investment> getInvestments() {
        return investments;
    }

    /**
     * @return the dataAsDate
     */
    public static LocalDate getDataAsDate() {
        return dataAsDate;
    }

    /**
     * Initializes the controller class.
     *
     * @param url
     * @param rb
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        txt_investiaURL.setText(PropertiesInit.getInvestiaURL());
        dtp_lastDate.setValue(LocalDate.parse(PropertiesInit.getLastGenUsedDate()));
        String[] clientNums = PropertiesInit.getClientNumList().split(",");
        for (String clientNum : clientNums) {
            if (!clientNum.trim().isEmpty()) {
                cbo_clientNum.getItems().add(clientNum.trim());
            }
        }
        Arrays.fill(linkAccountToLocalAccountIndex, -1);
        resetControls();

        cbo_clientNum.getEditor().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
            if (event.getCode() == KeyCode.DELETE) {
                cbo_clientNum.getItems().remove(cbo_clientNum.getValue());
                event.consume();
            }
        });

        dtp_lastDate.setConverter(new StringConverter<LocalDate>() {
            final String pattern = "yyyy-MM-dd";
            final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);

            {
                dtp_lastDate.setPromptText(pattern.toLowerCase());
            }

            @Override
            public String toString(LocalDate date) {
                if (date != null) {
                    return dateFormatter.format(date);
                } else {
                    return "";
                }
            }

            @Override
            public LocalDate fromString(String string) {
                if (string != null && !string.isEmpty()) {
                    return LocalDate.parse(string, dateFormatter);
                } else {
                    return null;
                }
            }
        });

        //This deals with the bug located here where the datepicker value is not updated on focus lost
        //https://bugs.openjdk.java.net/browse/JDK-8092295?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
        dtp_lastDate.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                if (!newValue) {
                    dtp_lastDate
                            .setValue(dtp_lastDate.getConverter().fromString(dtp_lastDate.getEditor().getText()));
                }
            }
        });
    }

    private void resetControls() {
        btn_login.setDisable(false);
        btn_logout.setDisable(true);
        cbo_clientNum.setDisable(false);
        cbo_clientNum.getEditor().setText("");
        cbo_accounts.getItems().clear();
        cbo_accounts.setDisable(true);
        psw_password.setDisable(false);
        psw_password.setText("");
        lbl_ownername.setText("");
        txt_investiaURL.setDisable(true);
        mnu_quitter.setDisable(false);
        btn_accounts.setDisable(true);
        btn_summary.setDisable(true);
    }

    private void setControlsOnceLogin() {
        btn_login.setDisable(true);
        btn_logout.setDisable(false);
        btn_accounts.setDisable(false);
        btn_summary.setDisable(false);
        mnu_quitter.setDisable(true);
        cbo_clientNum.setDisable(true);
        cbo_accounts.setDisable(false);
        lbl_ownername.setText(accountOwnerName);
        psw_password.setDisable(true);
        txt_investiaURL.setDisable(true);
        lbl_message.setText("");
        if (!cbo_clientNum.getItems().contains(cbo_clientNum.getEditor().getText())
                && !cbo_clientNum.getEditor().getText().trim().isEmpty()) {
            cbo_clientNum.getItems().add(cbo_clientNum.getEditor().getText());
        }
    }

    @FXML
    void handleBtnSummary(ActionEvent event) {
        ArrayList<Account> accountsToGen = new ArrayList<>();
        if ("Tous les comptes".equals(cbo_accounts.getSelectionModel().getSelectedItem())) {
            accountsToGen = accounts;
        } else {
            accountsToGen.add(accounts.get(cbo_accounts.getSelectionModel().getSelectedIndex()));
        }
        showAcountsInvestments(accountsToGen);
    }

    @FXML
    void handleMnuQuit(ActionEvent event) {
        InvestiaGenOFX.getWebClient().close();
        PropertiesInit.setInvestiaURL(txt_investiaURL.getText());
        PropertiesInit.setLastGenUsedDate(dtp_lastDate.getValue().toString());
        PropertiesInit.setClientNumList(cbo_clientNum.getItems().toString().replace("[", "").replace("]", ""));
        PropertiesInit.setProperties();
        Platform.exit();
        System.exit(0);
    }

    @FXML
    void handleBtnLogin(ActionEvent event) {
        try {
            if (InvestiaGenOFX.debug) {
                htmlPage = InvestiaGenOFX.getWebClient().getPage(InvestiaGenOFX.debugPath + "/Investia-Login.htm");
            } else {
                htmlPage = InvestiaGenOFX.getWebClient().getPage(txt_investiaURL.getText() + "?wcag=true");
            }
            HtmlForm form = htmlPage.getHtmlElementById("frmLogin");
            HtmlTextInput userId = form.getInputByName("UserName");
            HtmlPasswordInput password = form.getInputByName("Password");
            if (cbo_clientNum.getEditor().getText().length() == 0 || psw_password.getText().length() == 0) {
                lbl_message.setText("Le numro de client et mot de passe ne peuvent tre vide");
                return;
            }
            userId.setValueAttribute(cbo_clientNum.getEditor().getText());
            password.setValueAttribute(psw_password.getText());
            HtmlSubmitInput signInButton = (HtmlSubmitInput) form
                    .getByXPath("//input[contains(@class, 'btn-investia-blue')]").get(0);
            if (InvestiaGenOFX.debug) {
                htmlPage = InvestiaGenOFX.getWebClient().getPage(InvestiaGenOFX.debugFullPath + "-DashBoard.htm");
            } else {
                htmlPage = signInButton.click();
            }
        } catch (Exception ex) {
            lbl_message.setText("Le systme ne smble pas accessible. Voir le fichier de log...");
            Logger.getLogger(InvestiaGenOFXController.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }
        try {
            HtmlDivision div = (HtmlDivision) htmlPage
                    .getByXPath("//div[contains(@class, 'validation-summary-errors')]").get(0);
            lbl_message.setText(div.asText());
            return;
        } catch (Exception ex) { // do nothing
        }

        getAccountsFromWeb();
        setControlsOnceLogin();
        getAccountsInvestmentsFromWeb();
        setAccountsInvestmentsPercentage();
        for (Account account : accounts) {
            cbo_accounts.getItems().add(account.getAccountType());
        }
        cbo_accounts.getItems().add("Tous les comptes");
        cbo_accounts.setValue("Tous les comptes");
    }

    @FXML
    void handleBtnLogout(ActionEvent event) {
        try {
            if (InvestiaGenOFX.debug) {
                htmlPage = InvestiaGenOFX.getWebClient().getPage(InvestiaGenOFX.debugPath + "/Investia-Login.htm");
            } else {
                htmlPage = InvestiaGenOFX.getWebClient()
                        .getPage(txt_investiaURL.getText() + "/Account/LogOff" + "?wcag=true");
            }
            htmlPage.getHtmlElementById("frmLogin");
        } catch (Exception ex) {
            Logger.getLogger(InvestiaGenOFXController.class.getName()).log(Level.SEVERE, null, ex);
        }
        Arrays.fill(linkAccountToLocalAccountIndex, -1);
        PropertiesInit.removeUnknownAccounts();
        resetControls();
    }

    private void getAccountsFromWeb() {
        String name = "Nom Pastrouv";
        try {
            name = ((HtmlDivision) htmlPage.getHtmlElementById("phase1CustomerName")).asText();
            name = name.replace("Mme ", "").trim();
            name = name.replace("M. ", "").trim();
        } catch (ElementNotFoundException ex) {
            try {
                name = ((HtmlSelect) htmlPage.getHtmlElementById("selAccount")).asText();
                name = name.replaceAll("[^A-Za-z ]", "").trim();
            } catch (ElementNotFoundException ex2) {
            }
        }
        name = capitalizeFully(name);
        String[] token = name.split(" ");
        accountOwnerName = token[0] + " " + token[1];
        token = ((HtmlDivision) htmlPage.getByXPath("//div[contains(@class, 'col-xs-4 text-right')]").get(0))
                .asText().split(" ");
        dataAsDate = LocalDate.parse(token[token.length - 1], DateTimeFormatter.ISO_DATE);
        accounts = new ArrayList<>();
        try {
            if (InvestiaGenOFX.debug) {
                htmlPage = InvestiaGenOFX.getWebClient().getPage(InvestiaGenOFX.debugFullPath + "-Investments.htm");
            } else {
                htmlPage = InvestiaGenOFX.getWebClient()
                        .getPage(txt_investiaURL.getText() + "/Investments/ValueOf" + "?wcag=true");
            }

            List<?> sections = htmlPage.getByXPath("//section[not(contains(@id, 'valueOf'))]");
            for (int i = 1; i < sections.size(); i++) {
                HtmlSection section = (HtmlSection) sections.get(i);
                HtmlHeading4 h4 = (HtmlHeading4) section.getElementsByTagName("h4").get(0);
                token = h4.asText().replaceAll("[\\\\,]", "").split(" - ");
                Account account = new Account(token[0], token[1], dataAsDate);
                try {
                    HtmlHeading5 h5 = (HtmlHeading5) section.getElementsByTagName("h5").get(0);
                    token = h5.asText().split(" ");
                    if (token[0].startsWith("Numro")) {
                        account.setAccountID(token[token.length - 1]);
                    }
                } catch (IndexOutOfBoundsException ex) {
                }
                addAccount(account);
            }
        } catch (Exception ex) {
            Logger.getLogger(InvestiaGenOFXController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @FXML
    void handleBtnAccounts(ActionEvent event) {
        ArrayList<Account> accountsToGen = new ArrayList<>();
        if ("Tous les comptes".equals(cbo_accounts.getSelectionModel().getSelectedItem())) {
            accountsToGen = accounts;
        } else {
            accountsToGen.add(accounts.get(cbo_accounts.getSelectionModel().getSelectedIndex()));
        }
        getTransactionsFromWeb();
        String fileName = "";
        try {
            fileName = genOFXFile(accountsToGen);
        } catch (MyOwnException ex) {
            Logger.getLogger(InvestiaGenOFXController.class.getName()).log(Level.SEVERE, null, ex);
        }
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("Confirmation ");
        alert.setHeaderText(null);
        alert.setX(InvestiaGenOFX.getPrimaryStage().getX() + 100);
        alert.setY(InvestiaGenOFX.getPrimaryStage().getY() + 100);
        alert.setContentText("Fichier OFX gnr \rLance le fichier OFX?");
        ButtonType buttonTypeYes = new ButtonType("Oui");
        ButtonType buttonTypeNo = new ButtonType("Non");
        alert.getButtonTypes().setAll(buttonTypeYes, buttonTypeNo);
        Optional<ButtonType> result = alert.showAndWait();
        if (result.get() == buttonTypeYes) {
            try {
                Utilities.launchFile(fileName);
            } catch (IOException ex) {
                Logger.getLogger(InvestiaGenOFXController.class.getName()).log(Level.SEVERE, null, ex);
            }
            new File(fileName).deleteOnExit();
        }
        showAcountsInvestments(accountsToGen);
    }

    private void getTransactionsFromWeb() {
        try {
            if (!htmlPage.getUrl().toString().contains("/TransactionReports/Select")) {
                if (InvestiaGenOFX.debug) {
                    htmlPage = InvestiaGenOFX.getWebClient()
                            .getPage(InvestiaGenOFX.debugFullPath + "-Transactions.htm");
                } else {
                    htmlPage = InvestiaGenOFX.getWebClient()
                            .getPage(txt_investiaURL.getText() + "/TransactionReports/Select" + "?wcag=true");
                    waitForGeneratedTransactions();
                }
            }
            @SuppressWarnings(("unchecked"))
            List<HtmlHeading4> h4from = (List<HtmlHeading4>) htmlPage
                    .getByXPath("//h4[contains(text(),'Priode: de ')]");
            String from = h4from.get(0).asText();
            int index = from.indexOf("Priode: de ");
            LocalDate selFromDate = LocalDate.parse(from.substring(index + 12, index + 12 + 10));

            if (dtp_lastDate.getValue().isBefore(selFromDate)) {
                @SuppressWarnings(("unchecked"))
                List<HtmlForm> forms = (List<HtmlForm>) htmlPage.getByXPath("//form");
                HtmlForm form = forms.get(1);
                HtmlTextInput selPerFrom = form.getInputByName("selPerFrom");
                selPerFrom.setValueAttribute(dtp_lastDate.getValue().toString());

                HtmlAnchor generate = (HtmlAnchor) form.getByXPath("//a[contains(@class, 'btn-investia-blue')]")
                        .get(0);
                if (InvestiaGenOFX.debug) {
                    htmlPage = InvestiaGenOFX.getWebClient()
                            .getPage(InvestiaGenOFX.debugFullPath + "-Transactions.htm");
                } else {
                    htmlPage = generate.click();
                    waitForGeneratedTransactions();
                }
            }

            HtmlTable htmlTable = (HtmlTable) htmlPage.getElementById("tblTransactionReports");
            if (htmlTable == null) {
                return;
            }
            for (int i = 0; i < htmlTable.getRowCount(); i++) {
                LocalDate transacDate = LocalDate.parse(htmlTable.getCellAt(i, 0).getTextContent(),
                        DateTimeFormatter.ofPattern("dd MMM yyyy", Locale.CANADA_FRENCH));
                if (transacDate.isBefore(dtp_lastDate.getValue())) {
                    break;
                }
                String transacType = htmlTable.getCellAt(i, 2).getTextContent();
                String[] token = transacType.split("[\\-/(]");
                switch (token[0].replace(" ", "")) {
                case "Dividendes":
                    transacType = "Distribution";
                    break;
                case "Achat":
                case "changeentrant":
                case "Prlvementautomatique":
                case "Transfertentrantdecourtier":
                case "Transfertexterneentrant":
                case "Transfertinterneentrant":
                    transacType = "Purchase";
                    break;
                case "changesortant":
                case "Rachat":
                case "Transfertexternesortant":
                case "Transf.int.sort.":
                case "Transf.Int.sortant":
                case "Transfertinternesortant":
                    transacType = "Switch Out";
                    break;
                case "Dpt":
                    transacType = "Credit";
                    break;
                case "Retrait":
                case "Retenue":
                    transacType = "Debit";
                    break;
                case "Crditenespces":
                case "Entred'espces":
                case "Fraisd'administration":
                case "Sortied'espces":
                case "Transfertd'espcesentrant":
                case "Transfertd'espcessortant":
                    continue;
                default:
                    try {
                        throw new MyOwnException("Type de transaction non prise en charge: " + transacType.trim());
                    } catch (MyOwnException ex) {
                        Logger.getLogger(OFXUtilites.class.getName()).log(Level.SEVERE, null, ex);
                        continue;
                    }
                }

                String transacAccount = accountOwnerName.split(" ")[0] + "\\"
                        + htmlTable.getCellAt(i, 1).getTextContent();
                String symbol = htmlTable.getCellAt(i, 3).getTextContent();
                String unit = htmlTable.getCellAt(i, 5).getTextContent().replaceAll("[^0-9,]", "").replace(",",
                        ".");
                String fitid = "";
                String price = "0.00";
                String amount;
                if ("Credit".equals(transacType) || "Debit".equals(transacType)) {
                    amount = htmlTable.getCellAt(i, 9).getTextContent().replaceAll("[^0-9,]", "").replace(",", ".");
                    fitid = StringUtils.stripAccents(htmlTable.getCellAt(i, 2).getTextContent());
                } else {
                    amount = htmlTable.getCellAt(i, 10).getTextContent().replaceAll("[^0-9,]", "").replace(",",
                            ".");
                    price = Float.toString(Float.parseFloat(amount) / Float.parseFloat(unit));
                }
                if (PropertiesInit.getLinkAccountsTransac().indexOf(transacAccount) < 0) {
                    linkAccountTransac(transacAccount);
                }
                int idxAccount = linkAccountToLocalAccountIndex[PropertiesInit.getLinkAccountsTransac()
                        .indexOf(transacAccount)];
                accounts.get(idxAccount)
                        .add(new Transaction(transacDate, transacType, amount, fitid, symbol, unit, price, ""));
            }
        } catch (Exception ex) {
            Logger.getLogger(InvestiaGenOFXController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void waitForGeneratedTransactions() throws InterruptedException {
        for (int i = 0; i < 1000; i++) {
            if (((HtmlDivision) htmlPage.getHtmlElementById("divResult")).asText()
                    .contains("Gnration en cours")) {
                Thread.sleep(1000);
            } else {
                Thread.sleep(3000);
                break;
            }
        }
    }

    private void linkAccountTransac(String linkAccountTransac) {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(InvestiaGenOFX.class.getResource("view/linkaccountTransac.fxml"));
            AnchorPane page = (AnchorPane) loader.load();

            Stage dialogStage = new Stage();
            dialogStage.setTitle("Associer les comptes");
            dialogStage.getIcons().add(new Image("/myIcons/Teddy-Bear-Sick-icon.png"));
            dialogStage.initModality(Modality.WINDOW_MODAL);
            Scene scene = new Scene(page);
            dialogStage.initOwner(InvestiaGenOFX.getPrimaryStage());
            dialogStage.setScene(scene);
            InvestiaGenOFX.setOnCloseRequest(dialogStage);

            LinkaccountTransacController controller = loader.getController();
            controller.setlinkAccountTransac(linkAccountTransac);
            dialogStage.showAndWait();
        } catch (Exception ex) {
            Logger.getLogger(InvestiaGenOFXController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void getAccountsInvestmentsFromWeb() {
        @SuppressWarnings(("unchecked"))
        List<HtmlTable> tables = (List<HtmlTable>) htmlPage
                .getByXPath("//table[contains(@class, 'table-striped')]");
        @SuppressWarnings(("unchecked"))
        List<HtmlDivision> divBalancesAs = (List<HtmlDivision>) htmlPage
                .getByXPath("//div[contains(text(),'Soldes au')]");
        LocalDate balancesAs = LocalDate.parse(divBalancesAs.get(0).asText().replace("Soldes au ", ""),
                DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.CANADA_FRENCH));
        int i = 0;
        for (HtmlTable table : tables) {
            if (!table.asText().contains("Numro de \r\n compte")) {
                continue;
            }
            if (accounts.get(i).getAccountID() == null) {
                accounts.get(i).setAccountID(table.getCellAt(1, 3).getTextContent());
            }
            Float total = 0f;
            for (int j = 1; j < table.getRowCount(); j++) {
                String symbol = table.getCellAt(j, 1).getTextContent();
                String name = table.getCellAt(j, 0).getTextContent();
                String quantity = table.getCellAt(j, 5).getTextContent().replaceAll("[^0-9,]", "").replace(",",
                        ".");
                String lastPrice = table.getCellAt(j, 6).getTextContent().replaceAll("[^0-9,]", "").replace(",",
                        ".");
                String marketValue = table.getCellAt(j, 7).getTextContent().replaceAll("[^0-9,]", "").replace(",",
                        ".");
                Investment investment = new Investment(symbol, name, quantity, lastPrice, marketValue);
                accounts.get(i).add(investment);
                total += Float.valueOf(marketValue);
            }
            String totalString = String.format("%.02f", total);
            Investment investment = new Investment("", "Total", totalString, "1.00", totalString);
            accounts.get(i).add(investment);
            if (!balancesAs.equals(dataAsDate))
                accounts.get(i).setBalanceDate(balancesAs);
            i++;
        }
        if (!balancesAs.equals(dataAsDate))
            dataAsDate = balancesAs;
    }

    private void setAccountsInvestmentsPercentage() {
        for (int i = 0; i < accounts.size(); i++) {
            Float marketValue = Float.valueOf(accounts.get(i).getMarketValue());
            for (int j = 0; j < accounts.get(i).getInvestments().size(); j++) {
                Float invValue = accounts.get(i).getInvestments().get(j).getMarketValue();
                accounts.get(i).getInvestments().get(j).setPercentage(invValue / marketValue);
            }
        }
    }

    private void showAcountsInvestments(ArrayList<Account> accounts) {
        double x = InvestiaGenOFX.getPrimaryStage().getX();
        double y = InvestiaGenOFX.getPrimaryStage().getY();
        for (int i = 0; i < accounts.size(); i++) {
            investments = accounts.get(i).getInvestments();
            x = x + 20;
            y = y + 60;
            if (!"Unknown".equals(accounts.get(i).getAccountProvider())) {
                showInvestmentsSummary(accounts.get(i).getAccountType(), x, y);
            }
        }
    }

    private void showInvestmentsSummary(String accountType, Double x, Double y) {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(InvestiaGenOFX.class.getResource("view/investmentsSummary.fxml"));
            AnchorPane page = (AnchorPane) loader.load();

            Stage dialogStage = new Stage();
            dialogStage.setTitle("Sommaire des Investissements " + accountType);
            dialogStage.getIcons().add(new Image("/myIcons/Teddy-Bear-Sick-icon.png"));
            dialogStage.initModality(Modality.NONE);
            Scene scene = new Scene(page);
            dialogStage.initOwner(InvestiaGenOFX.getPrimaryStage());
            dialogStage.setX(x);
            dialogStage.setY(y);
            dialogStage.setScene(scene);
            dialogStage.show();
        } catch (Exception ex) {
            Logger.getLogger(InvestiaGenOFXController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @FXML
    void handleMnuAbout(ActionEvent event) {
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons()
                .add(new Image("/myIcons/Teddy-Bear-Sick-icon.png"));
        alert.setTitle("Information");
        alert.setX(InvestiaGenOFX.getPrimaryStage().getX() + 100);
        alert.setY(InvestiaGenOFX.getPrimaryStage().getY() + 100);
        alert.setHeaderText("InvestiaGenOFX");
        alert.setContentText("Version 2.0_6");
        alert.show();
    }
}