com.digitalgeneralists.assurance.ui.components.ResultsPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.digitalgeneralists.assurance.ui.components.ResultsPanel.java

Source

/*
 * Assurance
 * 
 * Created by Mark Johnson
 * 
 * Copyright (c) 2015 Digital Generalists, LLC.
 * 
 */
/*
 * Copyright 2015 Digital Generalists, LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */

package com.digitalgeneralists.assurance.ui.components;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.digitalgeneralists.assurance.IApplicationDelegate;
import com.digitalgeneralists.assurance.model.ModelUtils;
import com.digitalgeneralists.assurance.model.entities.ComparisonResult;
import com.digitalgeneralists.assurance.model.entities.Scan;
import com.digitalgeneralists.assurance.notification.IEventObserver;
import com.digitalgeneralists.assurance.notification.events.ComparisonResultAddedEvent;
import com.digitalgeneralists.assurance.notification.events.DeletedItemRestoreCompletedEvent;
import com.digitalgeneralists.assurance.notification.events.IAssuranceEvent;
import com.digitalgeneralists.assurance.notification.events.ResultMergeCompletedEvent;
import com.digitalgeneralists.assurance.notification.events.ScanCompletedEvent;
import com.digitalgeneralists.assurance.notification.events.ScanMergeCompletedEvent;
import com.digitalgeneralists.assurance.notification.events.ScanMergeProgressEvent;
import com.digitalgeneralists.assurance.notification.events.ScanMergeStartedEvent;
import com.digitalgeneralists.assurance.notification.events.ScanProgressEvent;
import com.digitalgeneralists.assurance.notification.events.ScanResultsLoadedEvent;
import com.digitalgeneralists.assurance.notification.events.ScanStartedEvent;
import com.digitalgeneralists.assurance.notification.events.SelectedScanChangedEvent;
import com.digitalgeneralists.assurance.notification.events.SetScanResultsMenuStateEvent;
import com.digitalgeneralists.assurance.ui.renderers.ComparisonResultListRenderer;

@Component("ResultsPanel")
public class ResultsPanel extends JPanel implements IEventObserver {
    private Logger logger = Logger.getLogger(ResultsPanel.class);

    @Autowired
    private ComparisonResultListRenderer comparisonResultListRenderer;

    private static final long serialVersionUID = 1L;

    private boolean initialized = false;

    @Autowired
    private ResultsMessagePanel messagePanel;

    @Autowired
    private IApplicationDelegate applicationDelegate;

    private final ResultsTableModel resultsTableModel = new ResultsTableModel();
    private final JTable resultsTable = new JTable(resultsTableModel);
    private final JScrollPane resultsScrollPane = new JScrollPane(this.resultsTable);

    private GridBagConstraints progressIndicatorConstraints = new GridBagConstraints();
    private GridBagConstraints resultsListConstraints = new GridBagConstraints();

    private final JLabel resultsLabel = new JLabel(" ");

    private final JProgressBar progressIndicator = new JProgressBar(0, 100);

    public ResultsPanel() {
        this.initializeComponent();
    }

    private void initializeComponent() {
        if (!this.initialized) {
            GridBagLayout gridbag = new GridBagLayout();
            this.setLayout(gridbag);

            ((DefaultTableCellRenderer) resultsTable.getTableHeader().getDefaultRenderer())
                    .setHorizontalAlignment(JLabel.CENTER);
            this.resultsTable.setRowHeight(150);

            ListSelectionModel selectionModel = this.resultsTable.getSelectionModel();

            selectionModel.addListSelectionListener(new ListSelectionListener() {
                public void valueChanged(ListSelectionEvent e) {
                    applicationDelegate.fireEvent(new SetScanResultsMenuStateEvent(false));
                    resultsTable.editCellAt(resultsTable.getSelectedRow(), 0);
                }
            });

            GridBagConstraints resultsLabelConstraints = new GridBagConstraints();
            resultsLabelConstraints.anchor = GridBagConstraints.WEST;
            resultsLabelConstraints.fill = GridBagConstraints.BOTH;
            resultsLabelConstraints.gridx = 0;
            resultsLabelConstraints.gridy = 0;
            resultsLabelConstraints.weightx = 1.0;
            resultsLabelConstraints.weighty = 0.1;
            resultsLabelConstraints.gridheight = 1;
            resultsLabelConstraints.gridwidth = 1;
            resultsLabelConstraints.insets = new Insets(5, 5, 5, 5);

            this.progressIndicatorConstraints.anchor = GridBagConstraints.WEST;
            this.progressIndicatorConstraints.fill = GridBagConstraints.BOTH;
            this.progressIndicatorConstraints.gridx = 0;
            this.progressIndicatorConstraints.gridy = 1;
            this.progressIndicatorConstraints.weightx = 1.0;
            this.progressIndicatorConstraints.weighty = 0.1;
            this.progressIndicatorConstraints.gridheight = 1;
            this.progressIndicatorConstraints.gridwidth = 1;
            this.progressIndicatorConstraints.insets = new Insets(5, 5, 5, 5);

            this.progressIndicator.setIndeterminate(true);

            this.resultsListConstraints.anchor = GridBagConstraints.WEST;
            this.resultsListConstraints.fill = GridBagConstraints.BOTH;
            this.resultsListConstraints.gridx = 0;
            this.resultsListConstraints.gridy = 2;
            this.resultsListConstraints.weightx = 1.0;
            this.resultsListConstraints.weighty = 0.9;
            this.resultsListConstraints.gridheight = 1;
            this.resultsListConstraints.gridwidth = 1;
            this.resultsListConstraints.insets = new Insets(5, 5, 5, 5);

            this.add(this.resultsLabel, resultsLabelConstraints);
            this.add(this.resultsScrollPane, this.resultsListConstraints);

            this.addAncestorListener(new AncestorListener() {
                public void ancestorAdded(AncestorEvent event) {
                    resultsTable.setDefaultRenderer(ComparisonResult.class, comparisonResultListRenderer);
                    resultsTable.setDefaultEditor(ComparisonResult.class, comparisonResultListRenderer);

                    applicationDelegate.addEventObserver(ScanStartedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(ComparisonResultAddedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(ScanResultsLoadedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(SelectedScanChangedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(ScanCompletedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(ScanProgressEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(ResultMergeCompletedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(ScanMergeStartedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(ScanMergeProgressEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(ScanMergeCompletedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.addEventObserver(DeletedItemRestoreCompletedEvent.class,
                            (IEventObserver) event.getSource());
                }

                public void ancestorRemoved(AncestorEvent event) {
                    applicationDelegate.removeEventObserver(ScanStartedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(ComparisonResultAddedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(ScanResultsLoadedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(SelectedScanChangedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(ScanCompletedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(ScanProgressEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(ResultMergeCompletedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(ScanMergeStartedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(ScanMergeProgressEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(ScanMergeCompletedEvent.class,
                            (IEventObserver) event.getSource());
                    applicationDelegate.removeEventObserver(DeletedItemRestoreCompletedEvent.class,
                            (IEventObserver) event.getSource());
                }

                public void ancestorMoved(AncestorEvent event) {
                }
            });

            this.initialized = true;
        }
    }

    public void resetPanel() {
        this.resultsTableModel.removeAllElements();
        this.conditionallyShowMessagePanel(false, "");
        this.resultsLabel.setText(" ");
    }

    private void conditionallyShowMessagePanel(boolean showMessagePanel, String message) {
        this.messagePanel.setMessage("");
        if (showMessagePanel) {
            this.messagePanel.setMessage(message);
            this.remove(this.resultsScrollPane);
            this.add(this.messagePanel, resultsListConstraints);
            this.validate();
            this.messagePanel.repaint();
        } else {
            this.add(this.resultsScrollPane, resultsListConstraints);
            this.remove(this.messagePanel);
            this.validate();
            this.resultsScrollPane.repaint();
        }
    }

    public void notify(IAssuranceEvent event) {
        StringBuffer loggingMessage = new StringBuffer(256);
        logger.info(loggingMessage.append("ResultsPanel received event: ").append(event));
        loggingMessage.setLength(0);
        loggingMessage = null;

        if (event instanceof SelectedScanChangedEvent) {
            this.resetPanel();
            StringBuilder labelText = new StringBuilder(512);
            this.resultsLabel
                    .setText(labelText.append("Results for ").append(event.getSource().toString()).toString());
            labelText.setLength(0);
            labelText = null;
        }

        if (event instanceof ScanStartedEvent) {
            this.resetPanel();
            StringBuilder labelText = new StringBuilder(512);
            this.resultsLabel.setText(
                    labelText.append("Loading results for ").append(event.getSource().toString()).toString());
            labelText.setLength(0);
            labelText = null;
            this.add(this.progressIndicator, this.progressIndicatorConstraints);
            this.validate();
            this.progressIndicator.repaint();
        }

        if (event instanceof ScanCompletedEvent) {
            this.applicationDelegate.loadScanResults((Scan) event.getSource());
            this.remove(this.progressIndicator);
            this.validate();
        }

        if (event instanceof ScanProgressEvent) {
            this.resultsLabel.setText(event.getSource().toString());
            this.validate();
        }

        if (event instanceof ScanResultsLoadedEvent) {
            int selectedResultIndex = this.resultsTable.getSelectedRow();

            Scan scan = (Scan) event.getSource();
            // NOTE:  Leaking model initialization like this into the UI is less than ideal.
            scan = (Scan) ModelUtils.initializeEntity(scan, Scan.RESULTS_PROPERTY);
            Collection<ComparisonResult> list = scan.getUnmodifiableResults();

            // NOTE:  Swapping the list model out to suppress change
            // notifications during a data reload feels less than ideal.
            this.resultsTable.setModel(new DefaultTableModel());

            this.resultsTableModel.removeAllElements();

            for (ComparisonResult result : list) {
                this.resultsTableModel.addRow(result);
                result = null;
            }

            this.resultsTable.setModel(this.resultsTableModel);

            this.conditionallyShowMessagePanel(list.size() == 0, "The source and target locations are identical.");
            list = null;

            StringBuilder labelText = new StringBuilder(512);
            this.resultsLabel.setText(labelText.append("Results for ").append(scan.toString()).toString());
            labelText.setLength(0);
            labelText = null;

            if ((selectedResultIndex >= 0) && (this.resultsTableModel.getRowCount() > selectedResultIndex)) {
                this.resultsTable.setRowSelectionInterval(selectedResultIndex, selectedResultIndex);
            }

            scan = null;
        }

        if ((event instanceof ResultMergeCompletedEvent) || (event instanceof DeletedItemRestoreCompletedEvent)) {
            for (int index = 0; index < this.resultsTableModel.getRowCount(); index++) {
                List<List<ComparisonResult>> resultList = new ArrayList<List<ComparisonResult>>(
                        this.resultsTableModel.data);
                if (((ComparisonResult) event.getSource()).getId() == resultList.get(index).get(0).getId()) {
                    this.resultsTableModel.updateRow(index, (ComparisonResult) event.getSource());
                }
                resultList = null;
            }
        }

        if (event instanceof ScanMergeStartedEvent) {
            this.resetPanel();
            StringBuilder labelText = new StringBuilder(512);
            this.resultsLabel.setText(labelText.append("Merging ").append(event.getSource().toString()).toString());
            labelText.setLength(0);
            labelText = null;
            this.add(this.progressIndicator, this.progressIndicatorConstraints);
            this.validate();
            this.progressIndicator.repaint();
            StringBuilder message = new StringBuilder(512);
            this.conditionallyShowMessagePanel(true,
                    message.append("Merging ").append(event.getSource().toString()).toString());
            message.setLength(0);
            message = null;
        }

        if (event instanceof ScanMergeProgressEvent) {
            this.resultsLabel.setText(event.getSource().toString());
            this.validate();
        }

        if (event instanceof ScanMergeCompletedEvent) {
            this.applicationDelegate.loadScanResults((Scan) event.getSource());
            this.remove(this.progressIndicator);
            this.validate();
        }
    }

    public ActionListener getResultMenuListener() {
        return this.comparisonResultListRenderer;
    }

    class ResultsTableModel extends AbstractTableModel {
        private static final long serialVersionUID = 1L;

        private String[] columnNames = { "Results" };
        private List<List<ComparisonResult>> data = new ArrayList<List<ComparisonResult>>();

        public int getRowCount() {
            return data.size();
        }

        public int getColumnCount() {
            return 1;
        }

        public String getColumnName(int columnIndex) {
            return columnNames[columnIndex];
        }

        public Class<? extends Object> getColumnClass(int columnIndex) {
            return ComparisonResult.class;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            if (data.size() == 0) {
                return null;
            }
            List<ComparisonResult> row = data.get(rowIndex);

            ComparisonResult result = row.get(0);
            row = null;

            return result;
        }

        public void setValueAt(Object value, int rowIndex, int columnIndex) {
            if (data.size() <= rowIndex) {
                List<ComparisonResult> row = new ArrayList<ComparisonResult>();
                row.add((ComparisonResult) value);
                data.add(row);
                row = null;
            } else {
                List<ComparisonResult> row = data.get(rowIndex);
                row.set(columnIndex, (ComparisonResult) value);
                row = null;
            }

            fireTableCellUpdated(rowIndex, columnIndex);
        }

        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        public void removeAllElements() {
            data.clear();
        }

        public void addRow(ComparisonResult result) {
            this.setValueAt(result, data.size(), 0);
        }

        public void updateRow(int rowIndex, ComparisonResult result) {
            this.setValueAt(result, rowIndex, 0);
        }
    }
}