Package org.eobjects.datacleaner.panels

Source Code of org.eobjects.datacleaner.panels.DatastoreListPanel

/**
* eobjects.org DataCleaner
* Copyright (C) 2010 eobjects.org
*
* 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.eobjects.datacleaner.panels;

import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
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.Inject;
import javax.inject.Provider;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;

import org.eobjects.analyzer.configuration.AnalyzerBeansConfiguration;
import org.eobjects.analyzer.connection.AccessDatastore;
import org.eobjects.analyzer.connection.CsvDatastore;
import org.eobjects.analyzer.connection.DataContextProvider;
import org.eobjects.analyzer.connection.Datastore;
import org.eobjects.analyzer.connection.DbaseDatastore;
import org.eobjects.analyzer.connection.ExcelDatastore;
import org.eobjects.analyzer.connection.FixedWidthDatastore;
import org.eobjects.analyzer.connection.JdbcDatastore;
import org.eobjects.analyzer.connection.OdbDatastore;
import org.eobjects.analyzer.connection.SasDatastore;
import org.eobjects.analyzer.connection.XmlDatastore;
import org.eobjects.analyzer.util.StringUtils;
import org.eobjects.datacleaner.database.DatabaseDriverCatalog;
import org.eobjects.datacleaner.database.DatabaseDriverDescriptor;
import org.eobjects.datacleaner.guice.InjectorBuilder;
import org.eobjects.datacleaner.user.DatastoreChangeListener;
import org.eobjects.datacleaner.user.MutableDatastoreCatalog;
import org.eobjects.datacleaner.util.DCDocumentListener;
import org.eobjects.datacleaner.util.IconUtils;
import org.eobjects.datacleaner.util.ImageManager;
import org.eobjects.datacleaner.util.WidgetFactory;
import org.eobjects.datacleaner.util.WidgetUtils;
import org.eobjects.datacleaner.widgets.Alignment;
import org.eobjects.datacleaner.widgets.DCLabel;
import org.eobjects.datacleaner.widgets.DCPopupBubble;
import org.eobjects.datacleaner.windows.AbstractFileBasedDatastoreDialog;
import org.eobjects.datacleaner.windows.AccessDatastoreDialog;
import org.eobjects.datacleaner.windows.AnalysisJobBuilderWindow;
import org.eobjects.datacleaner.windows.CompositeDatastoreDialog;
import org.eobjects.datacleaner.windows.CsvDatastoreDialog;
import org.eobjects.datacleaner.windows.DbaseDatastoreDialog;
import org.eobjects.datacleaner.windows.ExcelDatastoreDialog;
import org.eobjects.datacleaner.windows.FixedWidthDatastoreDialog;
import org.eobjects.datacleaner.windows.JdbcDatastoreDialog;
import org.eobjects.datacleaner.windows.OdbDatastoreDialog;
import org.eobjects.datacleaner.windows.OptionsDialog;
import org.eobjects.datacleaner.windows.SasDatastoreDialog;
import org.eobjects.datacleaner.windows.XmlDatastoreDialog;
import org.jdesktop.swingx.JXTextField;
import org.jdesktop.swingx.VerticalLayout;

import com.google.inject.Injector;

/**
* Panel to select which datastore to use. Shown in the "source" tab, if no
* datastore has been selected to begin with.
*
* @author Kasper Sørensen
*/
public class DatastoreListPanel extends DCPanel implements DatastoreChangeListener {

  private static final long serialVersionUID = 1L;

  private static final ImageManager imageManager = ImageManager.getInstance();
  private final MutableDatastoreCatalog _datastoreCatalog;
  private final AnalysisJobBuilderWindow _analysisJobBuilderWindow;
  private final Provider<OptionsDialog> _optionsDialogProvider;
  private final DatabaseDriverCatalog _databaseDriverCatalog;
  private final List<DatastorePanel> _datastorePanels = new ArrayList<DatastorePanel>();
  private final DCGlassPane _glassPane;
  private final JButton _analyzeButton;
  private final DCPanel _listPanel;
  private final JXTextField _searchDatastoreTextField;
  private final InjectorBuilder _injectorBuilder;

  @Inject
  protected DatastoreListPanel(AnalyzerBeansConfiguration configuration,
      AnalysisJobBuilderWindow analysisJobBuilderWindow, DCGlassPane glassPane,
      Provider<OptionsDialog> optionsDialogProvider, InjectorBuilder injectorBuilder,
      DatabaseDriverCatalog databaseDriverCatalog) {
    super();
    _datastoreCatalog = (MutableDatastoreCatalog) configuration.getDatastoreCatalog();
    _analysisJobBuilderWindow = analysisJobBuilderWindow;
    _glassPane = glassPane;
    _optionsDialogProvider = optionsDialogProvider;
    _injectorBuilder = injectorBuilder;
    _databaseDriverCatalog = databaseDriverCatalog;

    _datastoreCatalog.addListener(this);

    // initialize "analyze" button
    _analyzeButton = new JButton("Analyze!", imageManager.getImageIcon("images/filetypes/analysis_job.png"));
    _analyzeButton.setMargin(new Insets(1, 1, 1, 1));
    _analyzeButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        int i = 0;
        for (DatastorePanel datastorePanel : _datastorePanels) {
          if (datastorePanel.isSelected()) {
            Datastore datastore = datastorePanel.getDatastore();

            // open the connection here, to make any connection
            // issues apparent early
            DataContextProvider dataContextProvider = datastore.getDataContextProvider();
            dataContextProvider.getDataContext().getSchemaNames();
            _analysisJobBuilderWindow.setDatastore(datastore);
            dataContextProvider.close();
            return;
          }
          i++;
        }
      }
    });

    // initialize search text field
    _searchDatastoreTextField = WidgetFactory.createTextField("Search/filter datastores");
    _searchDatastoreTextField.setBorder(new CompoundBorder(new EmptyBorder(4, 0, 0, 0), WidgetUtils.BORDER_THIN));
    _searchDatastoreTextField.setOpaque(false);
    _searchDatastoreTextField.getDocument().addDocumentListener(new DCDocumentListener() {
      @Override
      protected void onChange(DocumentEvent event) {
        String text = _searchDatastoreTextField.getText();
        if (StringUtils.isNullOrEmpty(text)) {
          // when there is no search query, set all datastores visible
          for (DatastorePanel datastorePanel : _datastorePanels) {
            datastorePanel.setVisible(true);
          }
        } else {
          // do a case insensitive search
          text = text.trim().toLowerCase();
          for (DatastorePanel datastorePanel : _datastorePanels) {
            String name = datastorePanel.getDatastore().getName().toLowerCase();
            datastorePanel.setVisible(name.indexOf(text) != -1);
          }
          selectFirstVisibleDatastore();
        }
      }
    });
    _searchDatastoreTextField.addKeyListener(new KeyAdapter() {
      @Override
      public void keyPressed(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 VerticalLayout(4));

    final DCLabel headerLabel = DCLabel.dark("Select datastore for analysis");
    headerLabel.setFont(WidgetUtils.FONT_HEADER1);
    add(headerLabel);

    final DCLabel createNewDatastoreLabel = DCLabel.dark("Create a new datastore:");
    createNewDatastoreLabel.setFont(WidgetUtils.FONT_HEADER1);

    final DCPanel newDatastorePanel = new DCPanel();
    newDatastorePanel.setLayout(new VerticalLayout(4));
    newDatastorePanel.setBorder(new EmptyBorder(10, 10, 10, 0));
    newDatastorePanel.add(createNewDatastoreLabel);
    newDatastorePanel.add(createNewDatastorePanel());

    add(newDatastorePanel);

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

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

    add(buttonPanel);
  }

  private void updateDatastores() {
    _listPanel.removeAll();
    _datastorePanels.clear();

    final DCLabel existingDatastoresLabel = DCLabel.dark("Analyze an existing datastore:");
    existingDatastoresLabel.setFont(WidgetUtils.FONT_HEADER1);

    final DCPanel searchDatastorePanel = DCPanel.around(_searchDatastoreTextField);
    searchDatastorePanel.setBorder(WidgetUtils.BORDER_SHADOW);

    final DCPanel headerPanel = new DCPanel();
    headerPanel.setLayout(new FlowLayout(Alignment.LEFT.getFlowLayoutAlignment(), 0, 0));
    headerPanel.add(existingDatastoresLabel);
    headerPanel.add(Box.createHorizontalStrut(20));
    headerPanel.add(searchDatastorePanel);

    _listPanel.add(headerPanel);

    String[] datastoreNames = _datastoreCatalog.getDatastoreNames();
    for (int i = 0; i < datastoreNames.length; i++) {
      final Datastore datastore = _datastoreCatalog.getDatastore(datastoreNames[i]);
      DatastorePanel datastorePanel = new DatastorePanel(datastore, _datastoreCatalog, this,
          _analysisJobBuilderWindow.getWindowContext(), _injectorBuilder);
      _datastorePanels.add(datastorePanel);
      _listPanel.add(datastorePanel);
    }

    selectFirstVisibleDatastore();
  }

  private DCPanel createNewDatastorePanel() {
    final DCPanel panel = new DCPanel();
    panel.setBorder(WidgetUtils.BORDER_LIST_ITEM);
    panel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
    panel.add(createNewDatastoreButton("CSV file", "Comma-separated values (CSV) file (or file with other separators)",
        IconUtils.CSV_IMAGEPATH, CsvDatastore.class, CsvDatastoreDialog.class));
    panel.add(createNewDatastoreButton("Excel spreadsheet",
        "Microsoft Excel spreadsheet. Either .xls (97-2003) or .xlsx (2007+) format.", IconUtils.EXCEL_IMAGEPATH,
        ExcelDatastore.class, ExcelDatastoreDialog.class));
    panel.add(createNewDatastoreButton("Access database", "Microsoft Access database file (.mdb).",
        IconUtils.ACCESS_IMAGEPATH, AccessDatastore.class, AccessDatastoreDialog.class));
    panel.add(createNewDatastoreButton("SAS library", "A directory of SAS library files (.sas7bdat).",
        IconUtils.SAS_IMAGEPATH, SasDatastore.class, SasDatastoreDialog.class));
    panel.add(createNewDatastoreButton("DBase database", "DBase database file (.dbf)", IconUtils.DBASE_IMAGEPATH,
        DbaseDatastore.class, DbaseDatastoreDialog.class));
    panel.add(createNewDatastoreButton("Fixed width file",
        "Text file with fixed width values. Each value spans a fixed amount of text characters.",
        IconUtils.FIXEDWIDTH_IMAGEPATH, FixedWidthDatastore.class, FixedWidthDatastoreDialog.class));
    panel.add(createNewDatastoreButton("XML file", "Extensible Markup Language file (.xml)", IconUtils.XML_IMAGEPATH,
        XmlDatastore.class, XmlDatastoreDialog.class));
    panel.add(createNewDatastoreButton("OpenOffice.org Base database", "OpenOffice.org Base database file (.odb)",
        IconUtils.ODB_IMAGEPATH, OdbDatastore.class, OdbDatastoreDialog.class));

    panel.add(Box.createHorizontalStrut(20));

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

    createDefaultDatabaseButtons(panel, databaseNames);

    final JButton moreDatastoreTypesButton = new JButton("more");
    moreDatastoreTypesButton.setMargin(new Insets(1, 1, 1, 1));
    moreDatastoreTypesButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        final JPopupMenu popup = new JPopupMenu();

        final List<DatabaseDriverDescriptor> databaseDrivers = _databaseDriverCatalog
            .getInstalledWorkingDatabaseDrivers();
        for (DatabaseDriverDescriptor databaseDriver : databaseDrivers) {
          final String databaseName = databaseDriver.getDisplayName();
          if (!databaseNames.contains(databaseName)) {
            final String imagePath = databaseDriver.getIconImagePath();
            final ImageIcon icon = imageManager.getImageIcon(imagePath, IconUtils.ICON_SIZE_SMALL);
            final JMenuItem menuItem = WidgetFactory.createMenuItem(databaseName, icon);
            menuItem.addActionListener(createJdbcActionListener(databaseName));
            popup.add(menuItem);
          }
        }

        final JMenuItem compositeMenuItem = WidgetFactory.createMenuItem("Composite datastore",
            imageManager.getImageIcon(IconUtils.COMPOSITE_IMAGEPATH, IconUtils.ICON_SIZE_SMALL));
        compositeMenuItem.addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            new CompositeDatastoreDialog(_datastoreCatalog, _analysisJobBuilderWindow.getWindowContext())
                .setVisible(true);
          }
        });

        final JMenuItem databaseDriversMenuItem = WidgetFactory.createMenuItem("Manage database drivers...",
            imageManager.getImageIcon("images/menu/options.png", IconUtils.ICON_SIZE_SMALL));
        databaseDriversMenuItem.addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            OptionsDialog dialog = _optionsDialogProvider.get();
            dialog.selectDatabaseDriversTab();
            dialog.setVisible(true);
          }
        });

        popup.add(databaseDriversMenuItem);
        popup.add(new JSeparator(JSeparator.HORIZONTAL));
        popup.add(compositeMenuItem);
        popup.setBorder(WidgetUtils.BORDER_THIN);

        popup.show(moreDatastoreTypesButton, 0, moreDatastoreTypesButton.getHeight());
      }
    });

    panel.add(Box.createHorizontalStrut(10));
    panel.add(moreDatastoreTypesButton);

    return panel;
  }

  private void createDefaultDatabaseButtons(DCPanel panel, Set<String> databaseNames) {
    if (_databaseDriverCatalog.isInstalled(DatabaseDriverCatalog.DATABASE_NAME_MYSQL)) {
      panel.add(createNewJdbcDatastoreButton("MySQL connection", "Connect to a MySQL database",
          "images/datastore-types/databases/mysql.png", DatabaseDriverCatalog.DATABASE_NAME_MYSQL, databaseNames));
    }
    if (_databaseDriverCatalog.isInstalled(DatabaseDriverCatalog.DATABASE_NAME_POSTGRESQL)) {
      panel.add(createNewJdbcDatastoreButton("PostgreSQL connection", "Connect to a PostgreSQL database",
          "images/datastore-types/databases/postgresql.png", DatabaseDriverCatalog.DATABASE_NAME_POSTGRESQL,
          databaseNames));
    }
    if (_databaseDriverCatalog.isInstalled(DatabaseDriverCatalog.DATABASE_NAME_ORACLE)) {
      panel.add(createNewJdbcDatastoreButton("Oracle connection", "Connect to a Oracle database",
          "images/datastore-types/databases/oracle.png", DatabaseDriverCatalog.DATABASE_NAME_ORACLE, databaseNames));
    }
    if (_databaseDriverCatalog.isInstalled(DatabaseDriverCatalog.DATABASE_NAME_MICROSOFT_SQL_SERVER_JTDS)) {
      panel.add(createNewJdbcDatastoreButton("Microsoft SQL Server connection",
          "Connect to a Microsoft SQL Server database", "images/datastore-types/databases/microsoft.png",
          DatabaseDriverCatalog.DATABASE_NAME_MICROSOFT_SQL_SERVER_JTDS, databaseNames));
    }
  }

  private <D extends Datastore> JButton createNewDatastoreButton(final String title, final String description,
      final String imagePath, final Class<D> datastoreClass,
      final Class<? extends AbstractFileBasedDatastoreDialog<D>> dialogClass) {
    final ImageIcon icon = imageManager.getImageIcon(imagePath);
    final JButton button = WidgetFactory.createImageButton(icon);

    final DCPopupBubble popupBubble = new DCPopupBubble(_glassPane, "<html><b>" + title + "</b><br/>" + description
        + "</html>", 0, 0, imagePath);
    popupBubble.attachTo(button);

    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        Injector injectorWithNullDatastore = _injectorBuilder.with(datastoreClass, null).createInjector();
        AbstractFileBasedDatastoreDialog<D> dialog = injectorWithNullDatastore.getInstance(dialogClass);
        dialog.setVisible(true);
      }
    });
    return button;
  }

  private JButton createNewJdbcDatastoreButton(final String title, final String description, final String imagePath,
      final String databaseName, Set<String> databaseNames) {

    databaseNames.add(databaseName);

    final ImageIcon icon = imageManager.getImageIcon(imagePath);
    final JButton button = WidgetFactory.createImageButton(icon);

    final DCPopupBubble popupBubble = new DCPopupBubble(_glassPane, "<html><b>" + title + "</b><br/>" + description
        + "</html>", 0, 0, imagePath);
    popupBubble.attachTo(button);

    button.addActionListener(createJdbcActionListener(databaseName));

    return button;
  }

  private ActionListener createJdbcActionListener(final String databaseName) {
    return new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        Injector injectorWithDatastore = _injectorBuilder.with(JdbcDatastore.class, null).createInjector();
        JdbcDatastoreDialog dialog = injectorWithDatastore.getInstance(JdbcDatastoreDialog.class);
        dialog.setSelectedDatabase(databaseName);
        dialog.setVisible(true);
      }
    };
  }

  @Override
  public void removeNotify() {
    super.removeNotify();
    _datastoreCatalog.removeListener(this);
  }

  @Override
  public void onAdd(Datastore datastore) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        updateDatastores();
      }
    });
  }

  @Override
  public void onRemove(Datastore datastore) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        updateDatastores();
      }
    });
  }

  private void selectFirstVisibleDatastore() {
    boolean found = false;

    for (DatastorePanel datastorePanel : _datastorePanels) {
      if (datastorePanel.isVisible()) {
        setSelectedDatastorePanel(datastorePanel);
        found = true;
        break;
      }
    }

    _analyzeButton.setEnabled(found);
  }

  private void selectNextVisibleDatastore() {
    DatastorePanel selectedDatastorePanel = getSelectedDatastorePanel();
    if (selectedDatastorePanel != null) {

      int indexOf = _datastorePanels.indexOf(selectedDatastorePanel);
      for (int i = indexOf + 1; i < _datastorePanels.size(); i++) {
        DatastorePanel panel = _datastorePanels.get(i);
        if (panel.isVisible()) {
          setSelectedDatastorePanel(panel);
          break;
        }
      }
    }
  }

  private void selectPreviousVisibleDatastore() {
    DatastorePanel selectedDatastorePanel = getSelectedDatastorePanel();
    if (selectedDatastorePanel != null) {

      int indexOf = _datastorePanels.indexOf(selectedDatastorePanel);
      for (int i = indexOf - 1; i >= 0; i--) {
        DatastorePanel panel = _datastorePanels.get(i);
        if (panel.isVisible()) {
          setSelectedDatastorePanel(panel);
          break;
        }
      }
    }
  }

  public void setSelectedDatastorePanel(DatastorePanel datastorePanel) {
    for (DatastorePanel panel : _datastorePanels) {
      if (datastorePanel == panel) {
        panel.setSelected(true);
      } else {
        panel.setSelected(false);
      }
    }
    requestSearchFieldFocus();
  }

  public DatastorePanel getSelectedDatastorePanel() {
    for (DatastorePanel panel : _datastorePanels) {
      if (panel.isVisible() && panel.isSelected()) {
        return panel;
      }
    }
    return null;
  }

  public void clickAnalyzeButton() {
    if (_analyzeButton.isEnabled()) {
      _analyzeButton.doClick();
    }
  }

  public void requestSearchFieldFocus() {
    _searchDatastoreTextField.requestFocus();
  }
}
TOP

Related Classes of org.eobjects.datacleaner.panels.DatastoreListPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.