org.datacleaner.windows.OpenAnalysisJobAsTemplateDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.datacleaner.windows.OpenAnalysisJobAsTemplateDialog.java

Source

/**
 * DataCleaner (community edition)
 * Copyright (C) 2014 Neopost - Customer Information Management
 *
 * 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.windows;

import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.inject.Provider;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;

import org.apache.commons.vfs2.FileObject;
import org.apache.metamodel.schema.Column;
import org.apache.metamodel.util.CollectionUtils;
import org.apache.metamodel.util.FileHelper;
import org.datacleaner.actions.OpenAnalysisJobActionListener;
import org.datacleaner.bootstrap.WindowContext;
import org.datacleaner.configuration.DataCleanerConfiguration;
import org.datacleaner.configuration.SourceColumnMapping;
import org.datacleaner.connection.Datastore;
import org.datacleaner.connection.DatastoreCatalog;
import org.datacleaner.job.AnalysisJobMetadata;
import org.datacleaner.job.JaxbJobReader;
import org.datacleaner.job.builder.AnalysisJobBuilder;
import org.datacleaner.panels.DCPanel;
import org.datacleaner.util.IconUtils;
import org.datacleaner.util.ImageManager;
import org.datacleaner.util.WidgetFactory;
import org.datacleaner.util.WidgetUtils;
import org.datacleaner.widgets.DCComboBox.Listener;
import org.datacleaner.widgets.DCLabel;
import org.datacleaner.widgets.SourceColumnComboBox;
import org.jdesktop.swingx.HorizontalLayout;
import org.jdesktop.swingx.JXTextField;

import com.google.inject.Injector;

/**
 * Dialog for opening a job as a template. This feature allows the user to reuse
 * an existing job but on a new set of columns, typically from a different
 * datastore.
 */
public class OpenAnalysisJobAsTemplateDialog extends AbstractDialog {

    private static final long serialVersionUID = 1L;

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

    private final DataCleanerConfiguration _configuration;
    private final FileObject _file;
    private final AnalysisJobMetadata _metadata;
    private final SourceColumnMapping _sourceColumnMapping;
    private final DatastoreCatalog _datastoreCatalog;
    private final JComboBox<String> _datastoreCombobox;
    private final Map<String, List<SourceColumnComboBox>> _sourceColumnComboBoxes;
    private final Map<String, JXTextField> _variableTextFields;
    private final JButton _openButton;
    private final JButton _autoMapButton;
    private final Provider<OpenAnalysisJobActionListener> _openAnalysisJobActionListenerProvider;

    private volatile Datastore _datastore;

    public OpenAnalysisJobAsTemplateDialog(WindowContext windowContext, DataCleanerConfiguration configuration,
            FileObject file, AnalysisJobMetadata metadata,
            Provider<OpenAnalysisJobActionListener> openAnalysisJobActionListenerProvider) {
        super(windowContext, imageManager.getImage("images/window/banner-logo.png"));
        _configuration = configuration;
        _file = file;
        _metadata = metadata;
        _openAnalysisJobActionListenerProvider = openAnalysisJobActionListenerProvider;
        _sourceColumnMapping = new SourceColumnMapping(metadata);
        _variableTextFields = new HashMap<String, JXTextField>();

        _openButton = WidgetFactory.createPrimaryButton("Open job", IconUtils.MODEL_JOB);
        _openButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JaxbJobReader reader = new JaxbJobReader(_configuration);
                try {
                    SourceColumnMapping sourceColumnMapping = getSourceColumnMapping();

                    Map<String, String> variableOverrides = new HashMap<String, String>();
                    for (Entry<String, JXTextField> entry : _variableTextFields.entrySet()) {
                        variableOverrides.put(entry.getKey(), entry.getValue().getText());
                    }

                    final InputStream inputStream = _file.getContent().getInputStream();
                    final AnalysisJobBuilder ajb;
                    try {
                        ajb = reader.create(inputStream, sourceColumnMapping, variableOverrides);
                    } finally {
                        FileHelper.safeClose(inputStream);
                    }

                    final OpenAnalysisJobActionListener openAnalysisJobActionListener = _openAnalysisJobActionListenerProvider
                            .get();
                    final Injector injector = openAnalysisJobActionListener.openAnalysisJob(_file, ajb);

                    OpenAnalysisJobAsTemplateDialog.this.dispose();

                    final AnalysisJobBuilderWindow window = injector.getInstance(AnalysisJobBuilderWindow.class);
                    window.open();
                } catch (Exception e1) {
                    throw new IllegalStateException(e1);
                }
            }
        });

        final List<String> columnPaths = _metadata.getSourceColumnPaths();
        _sourceColumnComboBoxes = new HashMap<String, List<SourceColumnComboBox>>();
        for (String columnPath : columnPaths) {
            int columnDelim = columnPath.lastIndexOf('.');
            final String tablePath;
            if (columnDelim == -1) {
                // some column path contain only the column name
                tablePath = _metadata.getDatastoreName();
            } else {
                // this tablePath will be used to group together columns from
                // the same original table
                // The column's path contains also the table name in the path
                tablePath = columnPath.substring(0, columnDelim);
            }

            final SourceColumnComboBox comboBox = new SourceColumnComboBox();
            comboBox.setEnabled(false);
            comboBox.setName(columnPath);
            comboBox.addColumnSelectedListener(new Listener<Column>() {

                @Override
                public void onItemSelected(Column col) {
                    if (col != null) {
                        // make sure all comboboxes in a group use the same
                        // table
                        List<SourceColumnComboBox> comboBoxes = _sourceColumnComboBoxes.get(tablePath);
                        for (SourceColumnComboBox sameTableComboBox : comboBoxes) {
                            sameTableComboBox.setModel(_datastore, col.getTable());
                        }
                    }
                    refreshOpenButtonVisibility();
                }
            });

            if (!_sourceColumnComboBoxes.containsKey(tablePath)) {
                _sourceColumnComboBoxes.put(tablePath, new ArrayList<SourceColumnComboBox>());
            }

            _sourceColumnComboBoxes.get(tablePath).add(comboBox);
        }

        for (Entry<String, String> variableEntry : metadata.getVariables().entrySet()) {
            String id = variableEntry.getKey();
            String value = variableEntry.getValue();
            JXTextField textField = WidgetFactory.createTextField("Original: " + value);
            textField.setText(value);
            _variableTextFields.put(id, textField);
        }

        _openButton.setEnabled(false);
        _datastoreCatalog = configuration.getDatastoreCatalog();

        final String[] datastoreNames = _datastoreCatalog.getDatastoreNames();
        // the combobox will contain all datastore names and a null for
        // "not selected"
        final String[] comboBoxModel = CollectionUtils.array(new String[1], datastoreNames);
        _datastoreCombobox = new JComboBox<String>(comboBoxModel);
        _datastoreCombobox.setEditable(false);
        _datastoreCombobox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                final String datastoreName = (String) _datastoreCombobox.getSelectedItem();
                _datastore = _datastoreCatalog.getDatastore(datastoreName);

                _sourceColumnMapping.setDatastore(_datastore);

                refreshOpenButtonVisibility();

                for (List<SourceColumnComboBox> comboBoxes : _sourceColumnComboBoxes.values()) {
                    for (SourceColumnComboBox comboBox : comboBoxes) {
                        comboBox.setModel(_datastore);
                        if (_datastore == null) {
                            // no datastore selected
                            comboBox.setEnabled(false);
                        } else {
                            comboBox.setEnabled(true);
                        }
                    }
                }

                if (_datastore == null) {
                    _autoMapButton.setVisible(false);
                } else {
                    _autoMapButton.setVisible(true);
                }
            }
        });

        _autoMapButton = WidgetFactory.createDefaultButton("Map automatically");
        _autoMapButton.setVisible(false);
        _autoMapButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                _sourceColumnMapping.autoMap(_datastore);
                Set<String> paths = _sourceColumnMapping.getPaths();
                for (String path : paths) {
                    for (List<SourceColumnComboBox> comboBoxes : _sourceColumnComboBoxes.values()) {
                        for (SourceColumnComboBox comboBox : comboBoxes) {
                            if (path.equals(comboBox.getName())) {
                                comboBox.setSelectedItem(_sourceColumnMapping.getColumn(path));
                            }
                        }
                    }
                }
            }
        });
    }

    public void refreshOpenButtonVisibility() {
        if (_datastore == null) {
            // no datastore selected
            _openButton.setEnabled(false);
            return;
        }

        for (List<SourceColumnComboBox> comboBoxes : _sourceColumnComboBoxes.values()) {
            for (SourceColumnComboBox comboBox : comboBoxes) {
                if (comboBox.getSelectedItem() == null) {
                    // not all columns selected
                    _openButton.setEnabled(false);
                    return;
                }
            }
        }

        _openButton.setEnabled(true);
    }

    public SourceColumnMapping getSourceColumnMapping() {
        for (List<SourceColumnComboBox> comboBoxes : _sourceColumnComboBoxes.values()) {
            for (SourceColumnComboBox comboBox : comboBoxes) {
                _sourceColumnMapping.setColumn(comboBox.getName(), comboBox.getSelectedItem());
            }
        }
        return _sourceColumnMapping;
    }

    @Override
    protected String getBannerTitle() {
        return "Open as template";
    }

    @Override
    protected int getDialogWidth() {
        return 600;
    }

    @Override
    protected boolean isWindowResizable() {
        return true;
    }

    @Override
    protected JComponent getDialogContent() {
        final DCPanel panel = new DCPanel();

        int row = 0;
        WidgetUtils.addToGridBag(DCLabel.bright("<html><b>Original value:</b></html>"), panel, 1, row);
        WidgetUtils.addToGridBag(DCLabel.bright("<html><b>New/mapped value:</b></html>"), panel, 2, row);

        row++;
        WidgetUtils.addToGridBag(new JLabel(imageManager.getImageIcon(IconUtils.GENERIC_DATASTORE_IMAGEPATH)),
                panel, 0, row);
        WidgetUtils.addToGridBag(DCLabel.bright(_metadata.getDatastoreName()), panel, 1, row,
                GridBagConstraints.WEST);

        DCPanel datastoreButtonPanel = new DCPanel();
        datastoreButtonPanel.setLayout(new HorizontalLayout(0));
        datastoreButtonPanel.add(_datastoreCombobox);
        datastoreButtonPanel.add(Box.createHorizontalStrut(4));
        datastoreButtonPanel.add(_autoMapButton);

        WidgetUtils.addToGridBag(datastoreButtonPanel, panel, 2, row, GridBagConstraints.WEST);

        Set<String> tableNames = _sourceColumnComboBoxes.keySet();
        for (final String tableName : tableNames) {
            row++;
            final JLabel tableLabel = DCLabel.bright("<html><b>" + tableName + "</b></html>");
            tableLabel.setIcon(imageManager.getImageIcon(IconUtils.MODEL_TABLE, IconUtils.ICON_SIZE_SMALL));
            WidgetUtils.addToGridBag(tableLabel, panel, 0, row, 2, 1, GridBagConstraints.WEST);

            final JButton clearButton = WidgetFactory.createDefaultButton("Clear");
            clearButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    List<SourceColumnComboBox> comboBoxes = _sourceColumnComboBoxes.get(tableName);
                    for (SourceColumnComboBox comboBox : comboBoxes) {
                        comboBox.setModel(_datastore, false);
                    }
                }
            });
            final DCPanel clearButtonPanel = new DCPanel();
            clearButtonPanel.add(clearButton);
            WidgetUtils.addToGridBag(clearButtonPanel, panel, 2, row, GridBagConstraints.CENTER);

            final List<SourceColumnComboBox> comboBoxes = _sourceColumnComboBoxes.get(tableName);
            for (SourceColumnComboBox comboBox : comboBoxes) {
                row++;
                WidgetUtils.addToGridBag(
                        new JLabel(imageManager.getImageIcon(IconUtils.MODEL_COLUMN, IconUtils.ICON_SIZE_SMALL)),
                        panel, 0, row);
                WidgetUtils.addToGridBag(DCLabel.bright(comboBox.getName()), panel, 1, row,
                        GridBagConstraints.WEST);
                WidgetUtils.addToGridBag(comboBox, panel, 2, row, GridBagConstraints.WEST);
            }
        }
        row++;

        if (!_variableTextFields.isEmpty()) {
            final JLabel tableLabel = DCLabel.bright("<html><b>Job-level variables</b></html>");
            tableLabel.setIcon(imageManager.getImageIcon(IconUtils.MODEL_JOB, IconUtils.ICON_SIZE_SMALL));
            WidgetUtils.addToGridBag(tableLabel, panel, 0, row, 2, 1, GridBagConstraints.WEST);

            for (Entry<String, JXTextField> entry : _variableTextFields.entrySet()) {
                row++;
                String variableId = entry.getKey();
                JXTextField textField = entry.getValue();

                WidgetUtils.addToGridBag(
                        new JLabel(
                                imageManager.getImageIcon("images/model/variable.png", IconUtils.ICON_SIZE_SMALL)),
                        panel, 0, row);
                WidgetUtils.addToGridBag(DCLabel.bright(variableId), panel, 1, row, GridBagConstraints.WEST);
                WidgetUtils.addToGridBag(textField, panel, 2, row, GridBagConstraints.WEST);
            }
            row++;
        }

        final DCPanel openButtonPanel = new DCPanel();
        openButtonPanel.add(_openButton);
        WidgetUtils.addToGridBag(openButtonPanel, panel, 2, row, GridBagConstraints.EAST);

        return WidgetUtils.scrolleable(panel);
    }

    @Override
    public String getWindowTitle() {
        return "Open analysis job as template";
    }

}