biz.wolschon.finance.jgnucash.JGnucash.java Source code

Java tutorial

Introduction

Here is the source code for biz.wolschon.finance.jgnucash.JGnucash.java

Source

/**
 * JGnucash.java
 * Created on 16.05.2005
 * (c) 2005 by "Wolschon Softwaredesign und Beratung".
 *
 *  Permission is granted to use, modify, publish and sub-license this code
 *  as specified in the contract. If nothing else is specified these rights
 *  are given non-exclusively with no restrictions solely to the contractor(s).
 *  If no specified otherwise I reserve the right to use, modify, publish and
 *  sub-license this code to other parties myself.
 *
 * Otherwise, this code is made available under GPLv3 or later.
 *
 * -----------------------------------------------------------
 * major Changes:
 *  16.05.2005 - initial version
 *  06.11.2005 - added file-menu-plugins
 * ...
 *
 */
package biz.wolschon.finance.jgnucash;

import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;

import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.xml.bind.JAXBException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.java.plugin.PluginManager;
import org.java.plugin.registry.Extension;
import org.java.plugin.registry.ExtensionPoint;
import org.java.plugin.registry.IntegrityCheckReport;
import org.java.plugin.registry.PluginDescriptor;
import org.java.plugin.registry.Extension.Parameter;

import biz.wolschon.fileformats.gnucash.GnucashFile;
import biz.wolschon.fileformats.gnucash.GnucashWritableFile;
import biz.wolschon.fileformats.gnucash.jwsdpimpl.GnucashFileWritingImpl;
import biz.wolschon.finance.jgnucash.actions.AccountAction;
import biz.wolschon.finance.jgnucash.actions.ImportPluginMenuAction;
import biz.wolschon.finance.jgnucash.actions.OpenAccountInNewTabWritable;
import biz.wolschon.finance.jgnucash.actions.OpenAccountInNewWindowWritable;
import biz.wolschon.finance.jgnucash.actions.OpenFilePluginMenuAction;
import biz.wolschon.finance.jgnucash.actions.SaveAsFilePluginMenuAction;
import biz.wolschon.finance.jgnucash.actions.ToolPluginMenuAction;
import biz.wolschon.finance.jgnucash.actions.TransactionSplitAction;
import biz.wolschon.finance.jgnucash.panels.TransactionsPanel;
import biz.wolschon.finance.jgnucash.panels.WritableTransactionsPanel;

/**
 * created: 16.05.2005 <br/>
 *
 * (Shall become a simple java-reimplementation of gnucash
 * that can read and write gnucash-files.)<br/>
 *
 * Extended version of JGnucashViewer that allows for
 * changing and writing the gnucash-file.
 * <br/>
 * @author <a href="mailto:Marcus@Wolschon.biz">Marcus Wolschon</a>
 */
public class JGnucash extends JGnucashViewer {

    /**
     * empty constructor for GUI-designers.
     * DO NOT CALL.
     */
    public JGnucash() {
    }

    /**
     * Use this constructor.
     * @param manager the plugin-manager to use for loading plugins attached to extension-points of the main-plugin
     * @param descriptor the descriptor for the main-plugin
     */
    public JGnucash(final PluginManager manager, final PluginDescriptor descriptor) {
        this();
        setPluginManager(manager);
        setPluginDescriptor(descriptor);
        initializeGUI();
    }

    /**
     * Our logger for debug- and error-output.
     */
    static final Log LOGGER = LogFactory.getLog(JGnucash.class);

    /**
     * The data-model.
     */
    private GnucashWritableFile model;

    /**
     * Overridden to create  {@link GnucashWritableFile}.
     * ${@inheritDoc}.
     */
    @Override
    protected final GnucashFile createModelFromFile(final File f) throws IOException, JAXBException {
        //workaround because of a deadlock in log4j-consoleAppender in the JPf-classloader
        Logger.getLogger("org.java.plugin.standard.StandardPluginClassLoader").removeAllAppenders();
        Logger.getLogger("org.java.plugin.standard.StandardPluginClassLoader").setLevel(Level.FATAL);
        return new GnucashFileWritingImpl(f);
    }

    /**
     * @param args ignored.
     */
    public static void main(final String[] args) {
        JGnucash ste = new JGnucash();
        ste.setVisible(true);
    }

    /**
     * The file-menu.
     */
    private JMenu fileMenu;

    /**
     * File->Save.
     */
    private JMenuItem fileSaveMenuItem = null;

    /**
     * File->Save as...
     */
    private JMenuItem fileSaveAsMenuItem = null;

    //    /**
    //     * File-Menu to import other gnucash-files
    //     * into this one.
    //     */
    //    private JMenuItem fileImport = null;

    /**
     * The Import-Menu.
     */
    private JMenu importMenu = null;

    /**
     * The Import-Menu.
     */
    private JMenu toolMenu = null;

    /**
     * The main-entry-point to our plugin-api.
     */
    private PluginManager pluginManager = null;

    /**
     * The descriptor for our top-level application-plugin.
     */
    private PluginDescriptor pluginDescriptor = null;

    /**
     * The panel to show the current transactions.
     */
    private WritableTransactionsPanel writableTransactionsPanel;

    /**
     * True if we did make changes to our model.
     * Used to enable/disable the file->save -item.
     */
    private boolean hasChanged = false;

    /**
     * Our menu-bar.
     */
    private JMenuBar menuBar;

    /**
     * The "help"-menu.
     */
    private JMenu helpMenu;

    /**
     * The "help->PluginReport" menu-item.
     */
    private JMenuItem helpPluginReport;

    /**
     * The main-entry-point to our plugin-api.
     * @return the pluginManager
     */
    public PluginManager getPluginManager() {
        return pluginManager;
    }

    /**
     * The main-entry-point to our plugin-api.
     * @param aPluginManager the pluginManager to set
     */
    public void setPluginManager(final PluginManager aPluginManager) {
        pluginManager = aPluginManager;
    }

    /**
     * The descriptor for our top-level application-plugin.
     * @return the pluginDescriptor
     */
    public PluginDescriptor getPluginDescriptor() {
        return pluginDescriptor;
    }

    /**
     * The descriptor for our top-level application-plugin.
     * @param aPluginDescriptor the pluginDescriptor to set
     */
    public void setPluginDescriptor(final PluginDescriptor aPluginDescriptor) {
        pluginDescriptor = aPluginDescriptor;
    }

    /**
     * {@inheritDoc}
     * @see biz.wolschon.finance.jgnucash.JGnucashViewer#getHelpMenu()
     */
    @Override
    protected JMenu getHelpMenu() {
        if (helpMenu == null) {
            helpMenu = super.getHelpMenu();
            if (getPluginManager() != null) {
                helpMenu.add(getHelpPluginReportMenu());
            }
        }
        return helpMenu;
    }

    /**
     * @return a menu-item to show a report on plugin-loading
     */
    private JMenuItem getHelpPluginReportMenu() {
        if (helpPluginReport == null) {
            helpPluginReport = new JMenuItem();
            helpPluginReport.setText("Plugin Report");
            helpPluginReport.addActionListener(new ActionListener() {

                @SuppressWarnings("unchecked")
                @Override
                public void actionPerformed(final ActionEvent e) {
                    PluginManager manager = getPluginManager();
                    IntegrityCheckReport report = manager.getRegistry().getRegistrationReport();
                    StringBuilder message = new StringBuilder();
                    Collection<IntegrityCheckReport.ReportItem> items = report.getItems();
                    for (IntegrityCheckReport.ReportItem reportItem : items) {
                        String severity = ""; /*unknown: ";
                                              if (reportItem.getSeverity() == IntegrityCheckReport.ReportItem.SEVERITY_ERROR) {
                                              severity = "Error: ";
                                              } else if (reportItem.getSeverity() == IntegrityCheckReport.ReportItem.SEVERITY_WARNING) {
                                              severity = "Warning: ";
                                              } else if (reportItem.getSeverity() == IntegrityCheckReport.ReportItem.SEVERITY_INFO) {
                                              severity = "Info: ";
                                              };*/
                        message.append(severity)
                                /*.append('(')
                                .append(reportItem.getCode())
                                .append(')')*/
                                .append(reportItem.getMessage()).append('\n');
                    }
                    JOptionPane.showMessageDialog(JGnucash.this, message.toString(), "Plugins-Report",
                            JOptionPane.INFORMATION_MESSAGE);
                }
            });
        }
        return helpPluginReport;
    }

    /**
     * This method initializes transactionsPanel.
     *
     * @return javax.swing.JTable
     */
    @Override
    protected TransactionsPanel getTransactionsPanel() {
        return getWritableTransactionsPanel();
    }

    /**
     * This method initializes transactionsPanel.
     *
     * @return javax.swing.JTable
     */
    protected WritableTransactionsPanel getWritableTransactionsPanel() {
        if (writableTransactionsPanel == null) {
            writableTransactionsPanel = new WritableTransactionsPanel(getPluginManager(), getPluginDescriptor());
            writableTransactionsPanel.setSplitActions(getSplitActions());
        }
        return writableTransactionsPanel;
    }

    /**
     * {@inheritDoc}
     * @see biz.wolschon.finance.jgnucash.JGnucashViewer#getJMenuBar()
     */
    @Override
    public JMenuBar getJMenuBar() {
        if (menuBar == null) {
            menuBar = super.getJMenuBar();
            // insert the "Import"-menu before the help-menu.
            menuBar.add(getImportMenu(), menuBar.getMenuCount() - 1);
            menuBar.add(getToolMenu(), menuBar.getMenuCount() - 1);
        }
        return menuBar;
    }

    /**
     * This method initializes FileMenu
     * including all menu-items added by plugins.
     *
     * @return javax.swing.JMenu
     */
    @SuppressWarnings("unchecked")
    @Override
    protected JMenu getFileMenu() {
        if (fileMenu == null) {
            fileMenu = super.getFileMenu();
            fileMenu.setText("File");
            fileMenu.setMnemonic('f');
            int i = 1;
            fileMenu.add(getFileSaveMenuItem(), i++);
            fileMenu.add(getFileSaveAsMenuItem(), i++);

            // allow plugins to supply file-open and file-save -actions
            PluginManager manager = getPluginManager();
            // if we are configured for the plugin-api
            if (manager != null) {
                ExtensionPoint toolExtPoint = manager.getRegistry().getExtensionPoint(getPluginDescriptor().getId(),
                        "DataSource");
                for (Iterator<Extension> it = toolExtPoint.getConnectedExtensions().iterator(); it.hasNext();) {
                    Extension ext = it.next();
                    String pluginName = "unknown";

                    try {
                        pluginName = ext.getParameter("name").valueAsString();

                        LOGGER.debug("adding menu-item for DataSource-plugin " + pluginName
                                + " - support for writeTo=" + ext.getParameter("supportsWritingTo"));
                        JMenuItem newMenuItem = new JMenuItem();
                        newMenuItem.putClientProperty("extension", ext);
                        Parameter descrParam = ext.getParameter("description");
                        Parameter iconParam = ext.getParameter("icon");
                        URL iconUrl = null;
                        if (iconParam != null) {
                            try {
                                iconUrl = getPluginManager()
                                        .getPluginClassLoader(ext.getDeclaringPluginDescriptor())
                                        .getResource(iconParam.valueAsString());
                                if (iconUrl != null) {
                                    newMenuItem.setIcon(new ImageIcon(iconUrl));
                                }
                            } catch (Exception e) {
                                LOGGER.error("cannot load icon for Loader-Plugin '" + pluginName + "'", e);
                            }
                        }
                        newMenuItem.setText("open via " + pluginName + "...");
                        if (descrParam != null) {
                            newMenuItem.setToolTipText(descrParam.valueAsString());
                        }
                        newMenuItem.addActionListener(new OpenFilePluginMenuAction(this, ext, pluginName));
                        fileMenu.add(newMenuItem, 1); // Open
                        if (ext.getParameter("supportsWritingTo").valueAsString().equalsIgnoreCase("true")) {
                            LOGGER.debug("Plugin " + pluginName + " also supportes 'write to', adding menu-item");
                            JMenuItem newSaveAsMenuItem = new JMenuItem();
                            newSaveAsMenuItem.putClientProperty("extension", ext);
                            newSaveAsMenuItem.setText("Save to via " + pluginName + "...");
                            if (iconUrl != null) {
                                newMenuItem.setIcon(new ImageIcon(iconUrl));
                            }
                            newSaveAsMenuItem
                                    .addActionListener(new SaveAsFilePluginMenuAction(this, ext, pluginName));
                            fileMenu.add(newSaveAsMenuItem, 2); // Open

                        }
                    } catch (Exception e) {
                        LOGGER.error("cannot load Loader-Plugin '" + pluginName + "'", e);
                        JOptionPane.showMessageDialog(this, "Error",
                                "Cannot load Loader-Plugin '" + pluginName + "'", JOptionPane.ERROR_MESSAGE);
                    }
                }
            }
        }
        return fileMenu;
    }

    /**
     * This method initializes import-menu with
     * plugins.
     *
     * @return javax.swing.JMenu
     */
    @SuppressWarnings("unchecked")
    protected JMenu getImportMenu() {
        if (importMenu == null) {
            importMenu = new JMenu();
            importMenu.setText("Import");
            importMenu.setMnemonic('i');
            //importMenu.setEnabled(false);// first we need to load a file

            PluginManager manager = getPluginManager();
            // if we are configured for the plugin-api
            if (manager != null) {
                ExtensionPoint toolExtPoint = manager.getRegistry().getExtensionPoint(getPluginDescriptor().getId(),
                        "Importer");
                for (Iterator<Extension> it = toolExtPoint.getConnectedExtensions().iterator(); it.hasNext();) {
                    Extension ext = it.next();
                    String pluginName = "unknown";

                    try {
                        pluginName = ext.getParameter("name").valueAsString();
                        JMenuItem newMenuItem = new JMenuItem();
                        newMenuItem.putClientProperty("extension", ext);
                        Parameter descrParam = ext.getParameter("description");
                        Parameter iconParam = ext.getParameter("icon");
                        URL iconUrl = null;
                        if (iconParam != null) {
                            try {
                                iconUrl = getPluginManager()
                                        .getPluginClassLoader(ext.getDeclaringPluginDescriptor())
                                        .getResource(iconParam.valueAsString());
                                if (iconUrl != null) {
                                    newMenuItem.setIcon(new ImageIcon(iconUrl));
                                }
                            } catch (Exception e) {
                                LOGGER.error("cannot load icon for Importer-Plugin '" + pluginName + "'", e);
                            }
                        }
                        newMenuItem.setText(pluginName);
                        if (descrParam != null) {
                            newMenuItem.setToolTipText(descrParam.valueAsString());
                        }
                        newMenuItem.addActionListener(new ImportPluginMenuAction(this, ext, pluginName));
                        importMenu.add(newMenuItem);
                    } catch (Exception e) {
                        LOGGER.error("cannot load Importer-Plugin '" + pluginName + "'", e);
                        JOptionPane.showMessageDialog(this, "Error",
                                "Cannot load Importer-Plugin '" + pluginName + "'", JOptionPane.ERROR_MESSAGE);
                    }
                }
            }
        }
        return importMenu;
    }

    /**
     * This method initializes import-menu
     * with plugins.
     *
     * @return javax.swing.JMenu
     */
    @SuppressWarnings("unchecked")
    protected JMenu getToolMenu() {
        if (toolMenu == null) {
            toolMenu = new JMenu();
            toolMenu.setText("Tools");
            toolMenu.setMnemonic('t');
            //importMenu.setEnabled(false);// first we need to load a file

            PluginManager manager = getPluginManager();
            // if we are configured for the plugin-api
            if (manager != null) {
                ExtensionPoint toolExtPoint = manager.getRegistry().getExtensionPoint(getPluginDescriptor().getId(),
                        "Tool");
                for (Iterator<Extension> it = toolExtPoint.getConnectedExtensions().iterator(); it.hasNext();) {
                    Extension ext = it.next();
                    String pluginName = "unknown";

                    try {
                        pluginName = ext.getParameter("name").valueAsString();
                        JMenuItem newMenuItem = new JMenuItem();
                        newMenuItem.putClientProperty("extension", ext);
                        Parameter descrParam = ext.getParameter("description");
                        Parameter iconParam = ext.getParameter("icon");
                        URL iconUrl = null;
                        if (iconParam != null) {
                            try {
                                iconUrl = getPluginManager()
                                        .getPluginClassLoader(ext.getDeclaringPluginDescriptor())
                                        .getResource(iconParam.valueAsString());
                                if (iconUrl != null) {
                                    newMenuItem.setIcon(new ImageIcon(iconUrl));
                                }
                            } catch (Exception e) {
                                LOGGER.error("cannot load icon for Tool-Plugin '" + pluginName + "'", e);
                            }
                        }
                        newMenuItem.setText(pluginName);
                        if (descrParam != null) {
                            newMenuItem.setToolTipText(descrParam.valueAsString());
                        }
                        newMenuItem.addActionListener(new ToolPluginMenuAction(this, ext, pluginName));
                        toolMenu.add(newMenuItem);
                    } catch (Exception e) {
                        LOGGER.error("cannot load Tool-Plugin '" + pluginName + "'", e);
                        JOptionPane.showMessageDialog(this, "Error", "Cannot load Tool-Plugin '" + pluginName + "'",
                                JOptionPane.ERROR_MESSAGE);
                    }
                }
            }
        }
        return toolMenu;
    }

    /**
     * This method initializes fileSaveMenuItem.
     *
     * @return javax.swing.JMenuItem
     */
    private JMenuItem getFileSaveMenuItem() {
        if (fileSaveMenuItem == null) {
            fileSaveMenuItem = new JMenuItem();
            fileSaveMenuItem.setText("Save...");
            fileSaveMenuItem.setMnemonic('s');
            fileSaveMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(final java.awt.event.ActionEvent e) {
                    saveFile();
                }
            });
        }
        return fileSaveMenuItem;
    }

    /**
     * This method initializes fileSaveAsMenuItem.
     *
     * @return javax.swing.JMenuItem
     */
    private JMenuItem getFileSaveAsMenuItem() {
        if (fileSaveAsMenuItem == null) {
            fileSaveAsMenuItem = new JMenuItem();
            fileSaveAsMenuItem.setText("Save as...");
            fileSaveAsMenuItem.setMnemonic('a');
            fileSaveAsMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(final java.awt.event.ActionEvent e) {
                    saveFileAs();
                }
            });
        }
        return fileSaveAsMenuItem;
    }

    /**
     * Show the file->save as... -dialog.
     */
    private void saveFileAs() {
        int state = getJFileChooser().showSaveDialog(this);
        if (state == JFileChooser.APPROVE_OPTION) {
            File f = getJFileChooser().getSelectedFile();
            try {
                setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

                getWritableModel().writeFile(f);
                saveFile();
                setTitle(f.getName());
            } catch (FileNotFoundException e) {
                LOGGER.error("cannot save file '" + f.getAbsolutePath() + "' (file not found)", e);
                JOptionPane.showMessageDialog(this, "Error",
                        "cannot save file '" + f.getAbsolutePath() + "' (file not found)",
                        JOptionPane.ERROR_MESSAGE);
            } catch (IOException e) {
                LOGGER.error("cannot save file '" + f.getAbsolutePath() + "' (io-problem)", e);
                JOptionPane.showMessageDialog(this, "Error",
                        "cannot save file '" + f.getAbsolutePath() + "' (io-problem)", JOptionPane.ERROR_MESSAGE);
            } catch (JAXBException e) {
                LOGGER.error("cannot save file '" + f.getAbsolutePath() + "' (gnucash-format-problem)", e);
                JOptionPane.showMessageDialog(this, "Error",
                        "cannot save file '" + f.getAbsolutePath() + "' (gnucash-format-problem)",
                        JOptionPane.ERROR_MESSAGE);
            } finally {
                setCursor(Cursor.getDefaultCursor());
            }
        }
    }

    /**
     * @param x the exception to show
     */
    protected final void showErrorMessagePopup(final Exception x) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        x.printStackTrace(pw);
        pw.close();
        String file = "unknown";
        try {
            getJFileChooser().getSelectedFile().getAbsolutePath();
        } catch (Exception e) {
            e.printStackTrace();
        }
        JOptionPane.showMessageDialog(this, sw.toString(), "ERROR importing '" + file + "'",
                JOptionPane.ERROR_MESSAGE);
    }

    /**
     * @param f
     * @throws FileNotFoundException
     * @throws IOException
     * @throws JAXBException
     */
    private void saveFile() {
        try {
            File oldfile = new File(getWritableModel().getFile().getAbsolutePath());
            oldfile.renameTo(new File(oldfile.getName()
                    + (new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss.SS").format(new Date())) + ".backup"));

            getWritableModel().writeFile(getWritableModel().getFile());
            hasChanged = false;
        } catch (FileNotFoundException e) {
            File f = getWritableModel().getFile();
            if (f == null) {
                f = new File("unknown");
            }
            LOGGER.error("cannot save file '" + f.getAbsolutePath() + "' (file not found)", e);
            JOptionPane.showMessageDialog(this, "Error",
                    "cannot save file '" + f.getAbsolutePath() + "' (file not found)", JOptionPane.ERROR_MESSAGE);
        } catch (IOException e) {
            File f = getWritableModel().getFile();
            if (f == null) {
                f = new File("unknown");
            }
            LOGGER.error("cannot save file '" + f.getAbsolutePath() + "' (io-problem)", e);
            JOptionPane.showMessageDialog(this, "Error",
                    "cannot save file '" + f.getAbsolutePath() + "' (io-problem)", JOptionPane.ERROR_MESSAGE);
        } catch (JAXBException e) {
            File f = getWritableModel().getFile();
            if (f == null) {
                f = new File("unknown");
            }
            LOGGER.error("cannot save file '" + f.getAbsolutePath() + "' (gnucash-format-problem)", e);
            JOptionPane.showMessageDialog(this, "Error",
                    "cannot save file '" + f.getAbsolutePath() + "' (gnucash-format-problem)",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void doExit() {
        if (hasChanged) {
            int state = JOptionPane.showConfirmDialog(this, "File has been changed. Save before exit?");
            if (state == JOptionPane.YES_OPTION) {
                saveFile();
            } else if (state == JOptionPane.CANCEL_OPTION) {
                return;
            }
        }
        System.exit(0);
    }

    /**
    *
    * @return our model
    */
    public GnucashWritableFile getWritableModel() {
        return model;
    }

    /**
     * ${@inheritDoc}.
     */
    @Override
    protected GnucashFile getModel() {
        return model;
    }

    /**
     * ${@inheritDoc}.
     */
    @Override
    public void setModel(final GnucashFile newModel) {
        if (!(newModel instanceof GnucashWritableFile)) {
            throw new IllegalArgumentException("given model is not writable!");
        }
        setWritableModel((GnucashWritableFile) newModel);
    }

    /**
     *
     * @param newModel our new model
     */
    public void setWritableModel(final GnucashWritableFile newModel) {
        if (newModel == null) {
            throw new IllegalArgumentException("null not allowed for field this.model");
        }

        boolean ok = false;
        GnucashWritableFile oldModel = model;
        try {
            model = newModel;
            super.setModel(newModel);
            ok = true;
            hasChanged = false;
            getFileSaveAsMenuItem().setEnabled(true);
            getFileSaveMenuItem().setEnabled(true);
            getImportMenu().setEnabled(true);
        } finally {
            if (!ok) {
                model = oldModel;
            }
        }
    }

    /**
     * The actions we have on Splits.
     */
    private Collection<TransactionSplitAction> myWritableSplitActions;

    /**
     * The actions we have on accounts.
     */
    private Collection<AccountAction> myAccountActions;

    /**
     * @return the {@link AccountAction} we have
     */
    @Override
    protected Collection<TransactionSplitAction> getSplitActions() {
        if (myWritableSplitActions == null) {
            myWritableSplitActions = new LinkedList<TransactionSplitAction>();
            myWritableSplitActions.add(new OpenAccountInNewTabWritable(getJTabbedPane()));
            myWritableSplitActions.add(new OpenAccountInNewWindowWritable());
        }
        String actionsCount = "no";
        if (myWritableSplitActions != null) {
            actionsCount = "" + myWritableSplitActions.size();
        }
        LOGGER.info("JGnucashEditor has " + actionsCount + " split-actions");
        return myWritableSplitActions;
    }

    /**
     * @return the {@link AccountAction} we have including the ones offered by plugins.
     */
    @SuppressWarnings("unchecked")
    @Override
    protected Collection<AccountAction> getAccountActions() {
        if (myAccountActions == null) {
            myAccountActions = super.getAccountActions();

            PluginManager manager = getPluginManager();
            // if we are configured for the plugin-api
            if (manager != null) {
                ExtensionPoint toolExtPoint = manager.getRegistry().getExtensionPoint(getPluginDescriptor().getId(),
                        "AccountAction");
                for (Iterator<Extension> it = toolExtPoint.getConnectedExtensions().iterator(); it.hasNext();) {
                    Extension ext = it.next();
                    String pluginName = "unknown";

                    try {
                        getPluginManager().activatePlugin(ext.getDeclaringPluginDescriptor().getId());
                        // Get plug-in class loader.
                        ClassLoader classLoader = getPluginManager()
                                .getPluginClassLoader(ext.getDeclaringPluginDescriptor());
                        // Load Tool class.
                        Class toolCls = classLoader.loadClass(ext.getParameter("class").valueAsString());
                        // Create Tool instance.
                        Object o = toolCls.newInstance();
                        if (!(o instanceof AccountAction)) {
                            LOGGER.error("Plugin '" + pluginName + "' does not implement AccountAction-interface.");
                            JOptionPane.showMessageDialog(this, "Error",
                                    "The AccountAction-Plugin '" + pluginName + "'"
                                            + " does not implement AccountAction-interface.",
                                    JOptionPane.ERROR_MESSAGE);
                        } else {
                            myAccountActions.add((AccountAction) o);
                        }
                    } catch (Exception e) {
                        LOGGER.error("cannot load TransactionMenuAction-Plugin '" + pluginName + "'", e);
                        JOptionPane.showMessageDialog(this, "Error",
                                "Cannot load AccountAction-Plugin '" + pluginName + "'", JOptionPane.ERROR_MESSAGE);
                    }
                }
            }

        }
        return myAccountActions;
    }

}