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

org.datacleaner.panels.DatastoreManagementPanel Maven / Gradle / Ivy

There is a newer version: 6.0.0
Show newest version
/**
 * DataCleaner (community edition)
 * Copyright (C) 2014 Free Software Foundation, Inc.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program 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 Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.datacleaner.panels;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Provider;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;

import org.datacleaner.configuration.DataCleanerConfiguration;
import org.datacleaner.connection.Datastore;
import org.datacleaner.connection.DatastoreConnection;
import org.datacleaner.connection.DatastoreDescriptor;
import org.datacleaner.connection.DatastoreDescriptors;
import org.datacleaner.database.DatabaseDriverCatalog;
import org.datacleaner.guice.DCModule;
import org.datacleaner.user.DatastoreChangeListener;
import org.datacleaner.user.MutableDatastoreCatalog;
import org.datacleaner.user.UserPreferences;
import org.datacleaner.util.DCDocumentListener;
import org.datacleaner.util.IconUtils;
import org.datacleaner.util.ImageManager;
import org.datacleaner.util.StringUtils;
import org.datacleaner.util.WidgetFactory;
import org.datacleaner.util.WidgetUtils;
import org.datacleaner.widgets.Alignment;
import org.datacleaner.widgets.DCLabel;
import org.datacleaner.widgets.DCPopupBubble;
import org.datacleaner.widgets.PopupButton;
import org.datacleaner.widgets.PopupButton.MenuPosition;
import org.datacleaner.windows.AbstractDialog;
import org.datacleaner.windows.AnalysisJobBuilderWindow;
import org.datacleaner.windows.JdbcDatastoreDialog;
import org.datacleaner.windows.OptionsDialog;
import org.jdesktop.swingx.JXTextField;
import org.jdesktop.swingx.VerticalLayout;

import com.google.inject.Injector;

/**
 * Panel to select which job or datastore to use. Shown in the "source" tab, if
 * no datastore or job has been selected to begin with.
 */
public class DatastoreManagementPanel extends DCSplashPanel implements DatastoreChangeListener {

    private static final long serialVersionUID = 1L;

    private static final ImageManager imageManager = ImageManager.get();

    private final MutableDatastoreCatalog _datastoreCatalog;
    private final Provider _optionsDialogProvider;
    private final List _datastorePanels;
    private final DCGlassPane _glassPane;
    private final JButton _analyzeButton;
    private final DCPanel _datastoreListPanel;
    private final JXTextField _searchDatastoreTextField;
    private final DCModule _dcModule;
    private final DatabaseDriverCatalog _databaseDriverCatalog;
    private final UserPreferences _userPreferences;

    public DatastoreManagementPanel(final DataCleanerConfiguration configuration,
            final AnalysisJobBuilderWindow analysisJobBuilderWindow, final DCGlassPane glassPane,
            final Provider optionsDialogProvider, final DCModule dcModule,
            final DatabaseDriverCatalog databaseDriverCatalog, final UserPreferences userPreferences) {
        super(analysisJobBuilderWindow);

        _datastorePanels = new ArrayList<>();
        _datastoreCatalog = (MutableDatastoreCatalog) configuration.getDatastoreCatalog();
        _glassPane = glassPane;
        _optionsDialogProvider = optionsDialogProvider;
        _dcModule = dcModule;
        _databaseDriverCatalog = databaseDriverCatalog;
        _userPreferences = userPreferences;

        // initialize "Build job" button
        _analyzeButton = WidgetFactory.createPrimaryButton("Build job", IconUtils.MODEL_JOB);
        _analyzeButton.addActionListener(e -> {
            for (final DatastorePanel datastorePanel : _datastorePanels) {
                if (datastorePanel.isSelected()) {
                    final Datastore datastore = datastorePanel.getDatastore();

                    // open the connection here, to make any connection
                    // issues apparent early
                    try (DatastoreConnection datastoreConnection = datastore.openConnection()) {
                        datastoreConnection.getDataContext().getSchemaNames();
                        getWindow().setDatastore(datastore);
                    }
                    return;
                }
            }
        });

        // initialize search text field
        _searchDatastoreTextField = WidgetFactory.createTextField("Search/filter datastores");
        _searchDatastoreTextField.getDocument().addDocumentListener(new DCDocumentListener() {
            @Override
            protected void onChange(final DocumentEvent event) {
                String text = _searchDatastoreTextField.getText();
                if (StringUtils.isNullOrEmpty(text)) {
                    // when there is no search query, set all datastores
                    // visible
                    for (final DatastorePanel datastorePanel : _datastorePanels) {
                        datastorePanel.setVisible(true);
                    }
                } else {
                    // do a case insensitive search
                    text = text.trim().toLowerCase();
                    for (final DatastorePanel datastorePanel : _datastorePanels) {
                        final String name = datastorePanel.getDatastore().getName().toLowerCase();
                        datastorePanel.setVisible(name.indexOf(text) != -1);
                    }
                    selectFirstVisibleDatastore();
                }
            }
        });
        _searchDatastoreTextField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(final KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    clickAnalyzeButton();
                } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                    selectNextVisibleDatastore();
                } else if (e.getKeyCode() == KeyEvent.VK_UP) {
                    selectPreviousVisibleDatastore();
                }
            }
        });

        setLayout(new BorderLayout());

        final JComponent titleLabel = createTitleLabel("Datastore Management", true);
        add(titleLabel, BorderLayout.NORTH);

        final DCPanel containerPanel = new DCPanel();
        containerPanel.setLayout(new VerticalLayout(4));

        final DCLabel registerNewDatastoreLabel = DCLabel.dark("Register new:");
        registerNewDatastoreLabel.setFont(WidgetUtils.FONT_HEADER2);

        _datastoreListPanel = new DCPanel();
        _datastoreListPanel.setLayout(new VerticalLayout(4));
        _datastoreListPanel.setBorder(new EmptyBorder(10, 10, 4, 0));
        containerPanel.add(_datastoreListPanel);
        updateDatastores();

        final DCPanel buttonPanel = new DCPanel();
        buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 4, 0));
        buttonPanel.setBorder(new EmptyBorder(0, 10, 0, 0));
        buttonPanel.add(_analyzeButton);
        containerPanel.add(buttonPanel);

        add(wrapContent(containerPanel), BorderLayout.CENTER);

        final DCPanel newDatastorePanel = new DCPanel();
        newDatastorePanel.setLayout(new BorderLayout());
        newDatastorePanel.setBorder(new EmptyBorder(10, 10, 10, 0));
        newDatastorePanel.add(registerNewDatastoreLabel, BorderLayout.NORTH);
        newDatastorePanel.add(createNewDatastorePanel(), BorderLayout.CENTER);

        add(wrapContent(newDatastorePanel), BorderLayout.SOUTH);
    }

    private void updateDatastores() {
        final Datastore selectedDatastore = getSelectedDatastore();
        _datastoreListPanel.removeAll();
        _datastorePanels.clear();

        final DCLabel existingDatastoresLabel = DCLabel.dark("Existing datastores:");
        existingDatastoresLabel.setFont(WidgetUtils.FONT_HEADER2);

        final DCPanel headerPanel = new DCPanel();
        headerPanel.setLayout(new BorderLayout());
        headerPanel.add(existingDatastoresLabel, BorderLayout.WEST);
        headerPanel.add(_searchDatastoreTextField, BorderLayout.EAST);

        _datastoreListPanel.add(headerPanel);

        boolean selectFirst = true;

        final String[] datastoreNames = _datastoreCatalog.getDatastoreNames();
        for (int i = 0; i < datastoreNames.length; i++) {
            final Datastore datastore = _datastoreCatalog.getDatastore(datastoreNames[i]);
            final DatastorePanel datastorePanel =
                    new DatastorePanel(datastore, _datastoreCatalog, this, getWindow().getWindowContext(),
                            _userPreferences, _dcModule);
            _datastorePanels.add(datastorePanel);
            _datastoreListPanel.add(datastorePanel);

            if (selectedDatastore != null && selectedDatastore.getName().equals(datastore.getName())) {
                selectFirst = false;
                setSelectedDatastore(datastore);
            }
        }

        if (selectFirst) {
            selectFirstVisibleDatastore();
        }
    }

    public Datastore getSelectedDatastore() {
        final DatastorePanel datastorePanel = getSelectedDatastorePanel();
        if (datastorePanel == null) {
            return null;
        }
        return datastorePanel.getDatastore();
    }

    public void setSelectedDatastore(final Datastore datastore) {
        if (datastore != null) {
            for (final DatastorePanel panel : _datastorePanels) {
                if (datastore.equals(panel.getDatastore())) {
                    panel.setSelected(true);
                } else {
                    panel.setSelected(false);
                }
            }
        }
    }

    private DCPanel createNewDatastorePanel() {
        final int alignment = Alignment.LEFT.getFlowLayoutAlignment();
        final DCPanel panel1 = new DCPanel();

        panel1.setLayout(new FlowLayout(alignment, 10, 10));

        // set of databases that are displayed directly on panel
        final Set promotedDatabaseNames = new HashSet<>();

        final int panel1ItemsCount = 11;

        final DatastoreDescriptors datastoreDescriptors = new DatastoreDescriptors(_databaseDriverCatalog);
        for (int i = 0; i < Math.min(datastoreDescriptors.getAvailableDatastoreDescriptors().size(), panel1ItemsCount);
                i++) {
            final DatastoreDescriptor datastoreDescriptor =
                    datastoreDescriptors.getAvailableDatastoreDescriptors().get(i);
            if (datastoreDescriptor.isPromoted()) {
                panel1.add(createNewDatastoreButton(datastoreDescriptor.getName(), datastoreDescriptor.getDescription(),
                        datastoreDescriptor.getIconPath(), datastoreDescriptor.getDatastoreClass(),
                        datastoreDescriptor.getDatastoreDialogClass(), DCPopupBubble.Position.BOTTOM));
                promotedDatabaseNames.add(datastoreDescriptor.getName());
            }
        }

        final DCPanel panel2 = new DCPanel();
        panel2.setLayout(new FlowLayout(alignment, 10, 10));

        for (int i = panel1ItemsCount; i < datastoreDescriptors.getAvailableDatastoreDescriptors().size(); i++) {
            final DatastoreDescriptor datastoreDescriptor =
                    datastoreDescriptors.getAvailableDatastoreDescriptors().get(i);
            if (datastoreDescriptor.isPromoted()) {
                panel2.add(createNewDatastoreButton(datastoreDescriptor.getName(), datastoreDescriptor.getDescription(),
                        datastoreDescriptor.getIconPath(), datastoreDescriptor.getDatastoreClass(),
                        datastoreDescriptor.getDatastoreDialogClass(), DCPopupBubble.Position.TOP));
                promotedDatabaseNames.add(datastoreDescriptor.getName());
            }
        }

        panel2.add(Box.createHorizontalStrut(10));
        panel2.add(createMoreDatabasesButton(datastoreDescriptors.getAvailableDatastoreDescriptors(),
                promotedDatabaseNames));

        final DCPanel containerPanel = new DCPanel();
        containerPanel.setLayout(new BoxLayout(containerPanel, BoxLayout.Y_AXIS));
        containerPanel.add(panel1);
        containerPanel.add(panel2);

        return containerPanel;
    }

    private Component createMoreDatabasesButton(final List availableDatastoreDescriptors,
            final Set promotedDatabases) {
        final PopupButton moreDatastoreTypesButton =
                WidgetFactory.createDefaultPopupButton("More databases", IconUtils.GENERIC_DATASTORE_IMAGEPATH);
        moreDatastoreTypesButton.setMenuPosition(MenuPosition.TOP);

        final JPopupMenu moreDatastoreTypesMenu = moreDatastoreTypesButton.getMenu();

        for (int i = 0; i < availableDatastoreDescriptors.size(); i++) {
            final DatastoreDescriptor datastoreDescriptor = availableDatastoreDescriptors.get(i);
            if (!promotedDatabases.contains(datastoreDescriptor.getName())) {
                final String imagePath = datastoreDescriptor.getIconPath();
                final ImageIcon icon = imageManager.getImageIcon(imagePath, IconUtils.ICON_SIZE_SMALL);
                final JMenuItem menuItem = WidgetFactory.createMenuItem(datastoreDescriptor.getName(), icon);
                menuItem.addActionListener(
                        createActionListener(datastoreDescriptor.getName(), datastoreDescriptor.getDatastoreClass(),
                                datastoreDescriptor.getDatastoreDialogClass()));
                moreDatastoreTypesMenu.add(menuItem);
            }
        }

        moreDatastoreTypesMenu.addSeparator();

        final JMenuItem databaseDriversMenuItem = WidgetFactory.createMenuItem("Manage database drivers...",
                imageManager.getImageIcon(IconUtils.MENU_OPTIONS, IconUtils.ICON_SIZE_SMALL));
        databaseDriversMenuItem.addActionListener(e -> {
            final OptionsDialog dialog = _optionsDialogProvider.get();
            dialog.selectDatabaseDriversTab();
            dialog.setVisible(true);
        });

        moreDatastoreTypesMenu.add(databaseDriversMenuItem);
        return moreDatastoreTypesButton;
    }

    private  JButton createNewDatastoreButton(final String title, final String description,
            final String imagePath, final Class datastoreClass, final Class dialogClass,
            final DCPopupBubble.Position popupPosition) {
        final ImageIcon icon = imageManager.getImageIcon(imagePath, IconUtils.ICON_SIZE_LARGE);
        final JButton button = WidgetFactory.createImageButton(icon);

        final DCPopupBubble popupBubble =
                new DCPopupBubble(_glassPane, "" + title + "
" + description + "", 0, 0, icon, popupPosition); popupBubble.attachTo(button); button.addActionListener(createActionListener(title, datastoreClass, dialogClass)); return button; } private ActionListener createActionListener(final String title, final Class datastoreClass, final Class dialogClass) { return event -> { final Injector injectorWithNullDatastore = _dcModule.createInjectorBuilder().with(datastoreClass, null).createInjector(); final AbstractDialog dialog = injectorWithNullDatastore.getInstance(dialogClass); if (dialog instanceof JdbcDatastoreDialog) { final JdbcDatastoreDialog jdbcDatastoreDialog = (JdbcDatastoreDialog) dialog; jdbcDatastoreDialog.setSelectedDatabase(title); } dialog.setVisible(true); }; } @Override public void addNotify() { super.addNotify(); _datastoreCatalog.addListener(this); } @Override public void removeNotify() { super.removeNotify(); _datastoreCatalog.removeListener(this); } @Override public void onAdd(final Datastore datastore) { SwingUtilities.invokeLater(this::updateDatastores); } @Override public void onRemove(final Datastore datastore) { SwingUtilities.invokeLater(this::updateDatastores); } private void selectFirstVisibleDatastore() { boolean found = false; for (final DatastorePanel datastorePanel : _datastorePanels) { if (datastorePanel.isVisible()) { setSelectedDatastorePanel(datastorePanel); found = true; break; } } _analyzeButton.setEnabled(found); } private void selectNextVisibleDatastore() { final DatastorePanel selectedDatastorePanel = getSelectedDatastorePanel(); if (selectedDatastorePanel != null) { final int indexOf = _datastorePanels.indexOf(selectedDatastorePanel); for (int i = indexOf + 1; i < _datastorePanels.size(); i++) { final DatastorePanel panel = _datastorePanels.get(i); if (panel.isVisible()) { setSelectedDatastorePanel(panel); break; } } } } private void selectPreviousVisibleDatastore() { final DatastorePanel selectedDatastorePanel = getSelectedDatastorePanel(); if (selectedDatastorePanel != null) { final int indexOf = _datastorePanels.indexOf(selectedDatastorePanel); for (int i = indexOf - 1; i >= 0; i--) { final DatastorePanel panel = _datastorePanels.get(i); if (panel.isVisible()) { setSelectedDatastorePanel(panel); break; } } } } public DatastorePanel getSelectedDatastorePanel() { for (final DatastorePanel panel : _datastorePanels) { if (panel.isVisible() && panel.isSelected()) { return panel; } } return null; } public void setSelectedDatastorePanel(final DatastorePanel datastorePanel) { for (final DatastorePanel panel : _datastorePanels) { if (datastorePanel == panel) { panel.setSelected(true); } else { panel.setSelected(false); } } requestSearchFieldFocus(); } public void clickAnalyzeButton() { if (_analyzeButton.isEnabled()) { _analyzeButton.doClick(); } } public void requestSearchFieldFocus() { _searchDatastoreTextField.requestFocus(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy