org.datacleaner.widgets.result.AnnotatedRowsResultSwingRenderer Maven / Gradle / Ivy
/**
* 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.widgets.result;
import java.io.File;
import java.util.List;
import javax.inject.Inject;
import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JToolBar;
import javax.swing.border.EmptyBorder;
import javax.swing.table.TableModel;
import org.datacleaner.api.Description;
import org.datacleaner.api.InputColumn;
import org.datacleaner.api.InputRow;
import org.datacleaner.api.RendererBean;
import org.datacleaner.connection.DatastoreCatalog;
import org.datacleaner.output.OutputRow;
import org.datacleaner.output.OutputWriter;
import org.datacleaner.output.csv.CsvOutputWriterFactory;
import org.datacleaner.output.datastore.DatastoreCreationDelegate;
import org.datacleaner.output.datastore.DatastoreCreationDelegateImpl;
import org.datacleaner.output.datastore.DatastoreOutputWriterFactory;
import org.datacleaner.panels.DCPanel;
import org.datacleaner.result.AnnotatedRowsResult;
import org.datacleaner.result.renderer.AbstractRenderer;
import org.datacleaner.result.renderer.SwingRenderingFormat;
import org.datacleaner.user.MutableDatastoreCatalog;
import org.datacleaner.user.UserPreferences;
import org.datacleaner.util.FileFilters;
import org.datacleaner.util.IconUtils;
import org.datacleaner.util.ReflectionUtils;
import org.datacleaner.util.WidgetFactory;
import org.datacleaner.util.WidgetUtils;
import org.datacleaner.widgets.DCComboBox;
import org.datacleaner.widgets.DCFileChooser;
import org.datacleaner.widgets.DCLabel;
import org.datacleaner.widgets.PopupButton;
import org.datacleaner.widgets.table.ColumnHighlighter;
import org.datacleaner.widgets.table.DCTable;
import org.jdesktop.swingx.VerticalLayout;
import org.jdesktop.swingx.decorator.Highlighter;
@RendererBean(SwingRenderingFormat.class)
public class AnnotatedRowsResultSwingRenderer extends AbstractRenderer {
public static class AnnotatedRowResultPanel extends DCPanel {
private static final long serialVersionUID = 1L;
private final AnnotatedRowsResult _result;
private final UserPreferences _userPreferences;
private final DatastoreCatalog _datastoreCatalog;
private final DCTable _table;
public AnnotatedRowResultPanel(final AnnotatedRowsResult result, final UserPreferences userPreferences,
final DatastoreCatalog datastoreCatalog) {
super();
_result = result;
_userPreferences = userPreferences;
_datastoreCatalog = datastoreCatalog;
setLayout(new VerticalLayout(4));
_table = new DCTable();
_table.setColumnControlVisible(false);
final InputColumn>[] highlightedColumns = result.getHighlightedColumns();
final List> inputColumns = result.getInputColumns();
final JToolBar buttonToolBar = WidgetFactory.createToolBar();
buttonToolBar.setBorder(new EmptyBorder(0, 4, 0, 4));
final Description description = ReflectionUtils.getAnnotation(result.getClass(), Description.class);
final String descriptionText;
if (description != null) {
descriptionText = description.value();
} else {
descriptionText = "Records";
}
final int annotatedRowCount = result.getAnnotation().getRowCount();
final DCLabel label = DCLabel.dark(descriptionText + " (" + result.getAnnotatedRowCount() + ")");
label.setFont(WidgetUtils.FONT_HEADER1);
buttonToolBar.add(label);
buttonToolBar.add(WidgetFactory.createToolBarSeparator());
if (highlightedColumns.length == 1 && inputColumns.size() > 1) {
final DCComboBox comboBox = new DCComboBox<>(VIEWS);
comboBox.addListener(item -> {
if (item == VIEWS[0]) {
applyDetailedView();
} else {
applyDistinctValuesView();
}
});
comboBox.setSelectedItem(VIEWS[0]);
comboBox.notifyListeners();
buttonToolBar.add(comboBox);
} else {
applyDetailedView();
}
final PopupButton saveToFileButton = createSaveToFileButton(inputColumns);
buttonToolBar.add(saveToFileButton);
add(buttonToolBar);
if (annotatedRowCount == 0) {
final DCLabel noRecordsLabel = DCLabel.dark("No records to display.");
noRecordsLabel.setBorder(new EmptyBorder(0, 4, 0, 0));
add(noRecordsLabel);
} else {
final DCPanel tablePanel = _table.toPanel();
add(WidgetUtils.decorateWithShadow(tablePanel));
}
}
public void applyDistinctValuesView() {
final InputColumn>[] highlightedColumns = _result.getHighlightedColumns();
final TableModel tableModel = _result.toDistinctValuesTableModel(highlightedColumns[0]);
_table.setModel(tableModel);
_table.autoSetHorizontalScrollEnabled();
_table.setHighlighters(new Highlighter[0]);
}
public void applyDetailedView() {
_table.setModel(_result.toTableModel());
_table.autoSetHorizontalScrollEnabled();
final InputColumn>[] highlightedColumns = _result.getHighlightedColumns();
final List> inputColumns = _result.getInputColumns();
if (inputColumns.size() > highlightedColumns.length) {
// if there's context information available (columns
// besides the actual columns of interest) then highlight the
// columns of interest.
if (highlightedColumns.length > 0) {
final int[] highligthedColumnIndexes = new int[highlightedColumns.length];
for (int i = 0; i < highligthedColumnIndexes.length; i++) {
highligthedColumnIndexes[i] = _result.getColumnIndex(highlightedColumns[i]);
}
_table.addHighlighter(new ColumnHighlighter(highligthedColumnIndexes));
}
}
}
public PopupButton createSaveToFileButton(final List> inputColumns) {
final PopupButton saveToFileButton =
WidgetFactory.createDefaultPopupButton("Save dataset", IconUtils.ACTION_SAVE_DARK);
final JPopupMenu menu = saveToFileButton.getMenu();
final JMenuItem saveAsDatastoreItem =
WidgetFactory.createMenuItem("As datastore", IconUtils.GENERIC_DATASTORE_IMAGEPATH);
saveAsDatastoreItem.addActionListener(e -> {
final String datastoreName = JOptionPane.showInputDialog("Datastore name");
final DatastoreCreationDelegate creationDelegate =
new DatastoreCreationDelegateImpl((MutableDatastoreCatalog) _datastoreCatalog);
final OutputWriter writer = DatastoreOutputWriterFactory
.getWriter(_userPreferences.getSaveDatastoreDirectory(), creationDelegate, datastoreName,
"DATASET", inputColumns.toArray(new InputColumn[0]));
performWrite(writer);
});
final JMenuItem saveAsCsvItem = WidgetFactory.createMenuItem("As CSV file", IconUtils.CSV_IMAGEPATH);
saveAsCsvItem.addActionListener(e -> {
final DCFileChooser fileChooser = new DCFileChooser(_userPreferences.getAnalysisJobDirectory());
fileChooser.addChoosableFileFilter(FileFilters.CSV);
if (fileChooser.showSaveDialog(saveToFileButton) == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
if (selectedFile.getName().indexOf('.') == -1) {
selectedFile = new File(selectedFile.getPath() + ".csv");
}
final OutputWriter writer =
CsvOutputWriterFactory.getWriter(selectedFile.getAbsolutePath(), inputColumns);
performWrite(writer);
final File dir = selectedFile.getParentFile();
_userPreferences.setAnalysisJobDirectory(dir);
}
});
menu.add(saveAsCsvItem);
menu.add(saveAsDatastoreItem);
return saveToFileButton;
}
private void performWrite(final OutputWriter writer) {
for (final InputRow row : _result.getSampleRows()) {
final OutputRow outputRow = writer.createRow();
outputRow.setValues(row);
outputRow.write();
}
writer.close();
}
public DCTable getTable() {
return _table;
}
public AnnotatedRowsResult getResult() {
return _result;
}
}
private static final String[] VIEWS = new String[] { "View detailed rows", "View distinct values" };
@Inject
UserPreferences userPreferences;
@Inject
DatastoreCatalog datastoreCatalog;
@Override
public AnnotatedRowResultPanel render(final AnnotatedRowsResult result) {
return new AnnotatedRowResultPanel(result, userPreferences, datastoreCatalog);
}
}