/**
* 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.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import org.apache.metamodel.DataContext;
import org.apache.metamodel.DataContextFactory;
import org.apache.metamodel.data.DataSet;
import org.apache.metamodel.data.Row;
import org.apache.metamodel.query.Query;
import org.apache.metamodel.schema.Column;
import org.apache.metamodel.schema.Table;
import org.apache.metamodel.util.FileHelper;
import org.datacleaner.Version;
import org.datacleaner.bootstrap.DCWindowContext;
import org.datacleaner.bootstrap.WindowContext;
import org.datacleaner.panels.DCPanel;
import org.datacleaner.util.IconUtils;
import org.datacleaner.util.ImageManager;
import org.datacleaner.util.ResourceManager;
import org.datacleaner.util.StringUtils;
import org.datacleaner.util.WidgetFactory;
import org.datacleaner.util.WidgetUtils;
import org.datacleaner.widgets.DCLabel;
import org.datacleaner.widgets.DCListCellRenderer;
import org.datacleaner.widgets.NeopostToolbarButton;
import org.datacleaner.widgets.tabs.CloseableTabbedPane;
import org.jdesktop.swingx.HorizontalLayout;
import org.jdesktop.swingx.VerticalLayout;
import org.jdesktop.swingx.action.OpenBrowserAction;
/**
* The "About" dialog of the DataCleaner application.
*/
public class AboutDialog extends AbstractDialog {
public static class LicensedProject {
public String name;
public String websiteUrl;
public String license;
}
private static final long serialVersionUID = 1L;
private static final ResourceManager resourceManager = ResourceManager.get();
private static final ImageManager imageManager = ImageManager.get();
public AboutDialog(final WindowContext windowContext) {
super(windowContext);
}
public static List<LicensedProject> getLicensedProjects() {
final List<LicensedProject> result = new ArrayList<>();
final URL url = resourceManager.getUrl("licenses/dependency-licenses.csv");
if (url == null) {
throw new IllegalStateException("Could not find dependencies file");
}
try {
final DataContext dc = DataContextFactory.createCsvDataContext(url.openStream(), ',', '"');
final Table table = dc.getDefaultSchema().getTables()[0];
final Column projectColumn = table.getColumnByName("Project");
final Column websiteColumn = table.getColumnByName("Website");
final Column licenseColumn = table.getColumnByName("License");
final Query q = dc.query().from(table).select(table.getColumns()).orderBy(projectColumn).asc().toQuery();
final DataSet ds = dc.executeQuery(q);
while (ds.next()) {
final LicensedProject licensedProject = new LicensedProject();
final Row row = ds.getRow();
final String licenseName = row.getValue(licenseColumn).toString();
licensedProject.name = row.getValue(projectColumn).toString();
licensedProject.websiteUrl = row.getValue(websiteColumn).toString();
licensedProject.license = getLicense(licenseName);
result.add(licensedProject);
}
} catch (final IOException e) {
throw new IllegalStateException("Error occurred while reading dependencies file", e);
}
return result;
}
public static String getLicense(final String licenseName) {
final URL url = resourceManager.getUrl("licenses/" + licenseName + ".txt");
if (url == null) {
throw new IllegalArgumentException("Could not find license file for license: " + licenseName);
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(url.openStream(), FileHelper.UTF_8_ENCODING));
final StringBuilder sb = new StringBuilder();
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
if (sb.length() != 0) {
sb.append('\n');
}
sb.append(line);
}
return sb.toString();
} catch (final Exception e) {
throw new IllegalStateException("Error occurred while reading license file: " + licenseName, e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
// do nothing
}
}
}
}
@Override
public void toFront() {
super.toFront();
}
@Override
protected String getBannerTitle() {
return "About DataCleaner";
}
@Override
protected int getDialogWidth() {
return 650;
}
@Override
protected boolean isWindowResizable() {
return true;
}
@Override
protected JComponent getDialogContent() {
final CloseableTabbedPane tabbedPane = new CloseableTabbedPane(true);
tabbedPane.addTab("About DataCleaner",
imageManager.getImageIcon(IconUtils.APPLICATION_ICON, IconUtils.ICON_SIZE_LARGE), getAboutPanel(),
"About DataCleaner");
tabbedPane.setUnclosableTab(0);
tabbedPane.addTab("Licensing", imageManager.getImageIcon("images/menu/license.png"), getLicensingPanel(),
"Licensing");
tabbedPane.setUnclosableTab(1);
tabbedPane.setPreferredSize(new Dimension(getDialogWidth(), 500));
return tabbedPane;
}
private JComponent getLicensingPanel() {
final String dcLicense = getLicense("lgpl");
final DCLabel licenseHeader = DCLabel.dark("");
licenseHeader.setFont(WidgetUtils.FONT_HEADER1);
final DCLabel licenseLabel = DCLabel.darkMultiLine("");
licenseLabel.setBackground(WidgetUtils.BG_COLOR_BRIGHTEST);
licenseLabel.setFont(WidgetUtils.FONT_MONOSPACE);
licenseLabel.setOpaque(true);
final JButton dcLicenseButton = WidgetFactory.createSmallButton("images/menu/license.png");
dcLicenseButton.setToolTipText("DataCleaner's license: GNU LGPL");
dcLicenseButton.addActionListener(e -> {
licenseHeader.setText("Displaying license of DataCleaner");
licenseLabel.setText(dcLicense);
});
final JComboBox<Object> librariesComboBox = new JComboBox<>();
final JButton visitProjectButton = WidgetFactory.createSmallButton(IconUtils.WEBSITE);
librariesComboBox.setRenderer(new DCListCellRenderer() {
private static final long serialVersionUID = 1L;
@Override
public Component getListCellRendererComponent(final JList<?> list, final Object value, final int index,
final boolean isSelected, final boolean cellHasFocus) {
if (value instanceof LicensedProject) {
final LicensedProject project = (LicensedProject) value;
final String name = project.name;
return super.getListCellRendererComponent(list, name, index, isSelected, cellHasFocus);
} else if (value instanceof String) {
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
throw new UnsupportedOperationException();
}
});
librariesComboBox.addItemListener(e -> {
final Object item = e.getItem();
if (item instanceof LicensedProject) {
visitProjectButton.setEnabled(true);
final LicensedProject project = (LicensedProject) item;
licenseLabel.setText(project.license);
licenseHeader.setText("Displaying license of " + project.name + "");
} else {
visitProjectButton.setEnabled(false);
licenseHeader.setText("Displaying license of DataCleaner");
licenseLabel.setText(dcLicense);
}
});
visitProjectButton.addActionListener(e -> {
final Object item = librariesComboBox.getSelectedItem();
final LicensedProject project = (LicensedProject) item;
final String websiteUrl = project.websiteUrl;
if (!StringUtils.isNullOrEmpty(websiteUrl)) {
new OpenBrowserAction(websiteUrl).actionPerformed(e);
}
});
librariesComboBox.addItem("- select project -");
final List<LicensedProject> licensedProjects = getLicensedProjects();
for (final LicensedProject licensedProject : licensedProjects) {
librariesComboBox.addItem(licensedProject);
}
final JToolBar toolBar = WidgetFactory.createToolBar();
toolBar.add(DCLabel.dark("DataCleaners license: "));
toolBar.add(dcLicenseButton);
toolBar.add(WidgetFactory.createToolBarSeparator());
toolBar.add(DCLabel.dark("Included libraries: "));
toolBar.add(librariesComboBox);
toolBar.add(visitProjectButton);
final JScrollPane licenseLabelScroll = WidgetUtils.scrolleable(licenseLabel);
licenseLabelScroll.setBorder(new CompoundBorder(new EmptyBorder(10, 0, 10, 0), WidgetUtils.BORDER_THIN));
final DCPanel headerPanel = new DCPanel();
headerPanel.setLayout(new VerticalLayout());
headerPanel.add(toolBar);
headerPanel.add(Box.createVerticalStrut(20));
headerPanel.add(licenseHeader);
final DCPanel panel = new DCPanel(WidgetUtils.COLOR_DEFAULT_BACKGROUND);
panel.setBorder(new EmptyBorder(4, 4, 4, 4));
panel.setLayout(new BorderLayout());
panel.add(headerPanel, BorderLayout.NORTH);
panel.add(licenseLabelScroll, BorderLayout.CENTER);
return panel;
}
private JComponent getAboutPanel() {
final DCLabel headerLabel =
DCLabel.dark("DataCleaner " + Version.getEdition() + " " + Version.getDistributionVersion());
headerLabel.setFont(WidgetUtils.FONT_HEADER1);
final ImageManager imageManager = ImageManager.get();
final JButton datacleanerButton = new JButton(imageManager.getImageIcon("images/links/datacleaner.png"));
WidgetUtils.setDefaultButtonStyle(datacleanerButton);
datacleanerButton.addActionListener(new OpenBrowserAction("https://datacleaner.org"));
datacleanerButton.setToolTipText("Visit the DataCleaner website");
final JButton bloggerButton = new JButton(imageManager.getImageIcon("images/links/blogger.png"));
bloggerButton.addActionListener(new OpenBrowserAction("http://kasper.eobjects.org"));
bloggerButton.setToolTipText("Follow along at our blog");
WidgetUtils.setDefaultButtonStyle(bloggerButton);
final JButton linkedInButton = new JButton(imageManager.getImageIcon("images/links/linkedin.png"));
linkedInButton.addActionListener(new OpenBrowserAction("http://www.linkedin.com/groups?gid=3352784"));
linkedInButton.setToolTipText("Join the DataCleaner LinkedIn group");
WidgetUtils.setDefaultButtonStyle(linkedInButton);
final DCPanel buttonPanel = new DCPanel();
buttonPanel.setLayout(new HorizontalLayout());
buttonPanel.add(datacleanerButton);
buttonPanel.add(Box.createHorizontalStrut(10));
buttonPanel.add(bloggerButton);
buttonPanel.add(Box.createHorizontalStrut(10));
buttonPanel.add(linkedInButton);
final NeopostToolbarButton neopostButton =
new NeopostToolbarButton(imageManager.getImageIcon("images/powered-by-neopost-bright.png"));
final DCPanel contentPanel = new DCPanel();
contentPanel.setLayout(new VerticalLayout());
contentPanel.add(headerLabel);
contentPanel.add(DCLabel.dark("Core version " + Version.getVersion()));
contentPanel.add(DCLabel.dark("Copyright (C) " + Calendar.getInstance().get(Calendar.YEAR) + " Neopost"));
contentPanel.add(Box.createVerticalStrut(20));
contentPanel.add(DCPanel.around(neopostButton));
if (Version.isCommunityEdition()) {
contentPanel.add(Box.createVerticalStrut(20));
contentPanel.add(DCLabel.dark("Licensed under the LGPL license"));
contentPanel.add(DCLabel.dark("(see Licensing tab)."));
} else {
final String licenseKey = Version.getLicenseKey();
contentPanel.add(Box.createVerticalStrut(20));
contentPanel.add(DCLabel.dark("License key: " + licenseKey));
}
contentPanel.add(Box.createVerticalStrut(30));
contentPanel.add(DCLabel.dark("Java runtime information:"));
contentPanel.add(DCLabel.dark(" " + System.getProperty("java.vm.name")));
contentPanel.add(DCLabel.dark(" by " + System.getProperty("java.vm.vendor")));
contentPanel.add(DCLabel.dark(" version " + System.getProperty("java.runtime.version")));
contentPanel.add(Box.createVerticalStrut(30));
contentPanel.add(buttonPanel);
final DCPanel mainPanel = new DCPanel(imageManager.getImage("images/window/app-icon-hires.png"), 97, 10,
WidgetUtils.COLOR_DEFAULT_BACKGROUND);
mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
mainPanel.setLayout(new VerticalLayout());
mainPanel.add(contentPanel);
return mainPanel;
}
@Override
public String getWindowTitle() {
return "About DataCleaner | DataCleaner";
}
public static void main(final String[] args) {
new AboutDialog(new DCWindowContext(null, null, null)).setVisible(true);
}
}