eu.lp0.cursus.ui.event.EventAttendeesTab.java Source code

Java tutorial

Introduction

Here is the source code for eu.lp0.cursus.ui.event.EventAttendeesTab.java

Source

/*
   cursus - Race series management program
   Copyright 2012-2014  Simon Arlott
    
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
    
   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 Affero General Public License for more details.
    
   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package eu.lp0.cursus.ui.event;

import java.awt.BorderLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.persistence.PersistenceException;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.SwingUtilities;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Objects;
import com.google.common.base.Predicates;
import com.google.common.collect.Sets;

import eu.lp0.cursus.db.DatabaseSession;
import eu.lp0.cursus.db.dao.EventDAO;
import eu.lp0.cursus.db.dao.PilotDAO;
import eu.lp0.cursus.db.data.Event;
import eu.lp0.cursus.db.data.Sex;
import eu.lp0.cursus.db.data.Pilot;
import eu.lp0.cursus.db.data.Race;
import eu.lp0.cursus.db.data.RaceNumber;
import eu.lp0.cursus.ui.Constants;
import eu.lp0.cursus.ui.component.AbstractDatabaseTab;
import eu.lp0.cursus.ui.component.BooleanDatabaseColumn;
import eu.lp0.cursus.ui.component.DatabaseColumn;
import eu.lp0.cursus.ui.component.DatabaseTableModel;
import eu.lp0.cursus.ui.component.DatabaseWindow;
import eu.lp0.cursus.ui.component.EnumDatabaseColumn;
import eu.lp0.cursus.ui.component.StringDatabaseColumn;
import eu.lp0.cursus.ui.table.RaceNumbersDatabaseColumnModel;
import eu.lp0.cursus.util.Background;
import eu.lp0.cursus.util.DatabaseError;

public class EventAttendeesTab extends AbstractDatabaseTab<Event> {
    private final Logger log = LoggerFactory.getLogger(getClass());
    private JScrollPane scrollPane;
    private JTable table;
    private DatabaseTableModel<Pilot> model;
    private Event currentEvent;

    private static final EventDAO eventDAO = new EventDAO();
    private static final PilotDAO pilotDAO = new PilotDAO();

    public EventAttendeesTab(DatabaseWindow win) {
        super(Event.class, win, "tab.pilots"); //$NON-NLS-1$
        initialise();
    }

    @SuppressWarnings("unchecked")
    private void initialise() {
        setLayout(new BorderLayout(0, 0));

        scrollPane = new JScrollPane();
        add(scrollPane, BorderLayout.CENTER);

        table = new JTable();
        scrollPane.setViewportView(table);

        model = new DatabaseTableModel<Pilot>(Arrays.<DatabaseColumn<Pilot, ?>>asList( //
                new BooleanDatabaseColumn<Pilot>("pilot.event-attendee", win, pilotDAO) { //$NON-NLS-1$
                    @Override
                    protected Boolean getValue(Pilot row, boolean editing) {
                        assert (currentEvent != null);
                        return row.getEvents().contains(currentEvent);
                    }

                    @Override
                    protected boolean setValue(Pilot row, Boolean value) {
                        assert (currentEvent != null);
                        if (value) {
                            row.getEvents().add(currentEvent);
                        } else {
                            row.getEvents().remove(currentEvent);
                        }
                        return true;
                    }
                }, new StringDatabaseColumn<Pilot>("pilot.race-count") { //$NON-NLS-1$
                    @Override
                    protected String getValue(Pilot row, boolean editing) {
                        return String.valueOf(Sets
                                .filter(row.getRaces().keySet(), Predicates.in(currentEvent.getRaces())).size());
                    }

                    @Override
                    protected boolean setValue(Pilot row, String value) {
                        return false;
                    }
                }, new RaceNumbersDatabaseColumnModel("pilot.race-number"), //$NON-NLS-1$
                new StringDatabaseColumn<Pilot>("pilot.name") { //$NON-NLS-1$
                    @Override
                    protected String getValue(Pilot row, boolean editing) {
                        return row.getName();
                    }

                    @Override
                    protected boolean setValue(Pilot row, String value) {
                        return false;
                    }
                }, new EnumDatabaseColumn<Pilot, Sex>("pilot.sex", Sex.class, true) { //$NON-NLS-1$
                    @Override
                    protected Sex getEnumValue(Pilot row) {
                        return row.getSex();
                    }

                    @Override
                    protected boolean setEnumValue(Pilot row, Sex value) {
                        return false;
                    }
                }, new StringDatabaseColumn<Pilot>("pilot.country") { //$NON-NLS-1$
                    @Override
                    protected String getValue(Pilot row, boolean editing) {
                        return row.getCountry();
                    }

                    @Override
                    protected boolean setValue(Pilot row, String value) {
                        return false;
                    }
                }));
        model.setupModel(table);
        table.getRowSorter().setSortKeys(Arrays.asList(new RowSorter.SortKey(0, SortOrder.DESCENDING),
                new RowSorter.SortKey(1, SortOrder.ASCENDING), new RowSorter.SortKey(2, SortOrder.ASCENDING),
                new RowSorter.SortKey(3, SortOrder.ASCENDING), new RowSorter.SortKey(4, SortOrder.ASCENDING),
                new RowSorter.SortKey(5, SortOrder.ASCENDING)));

        table.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent ke) {
                if (ke.isConsumed()) {
                    return;
                }
                if (ke.getKeyCode() == KeyEvent.VK_INSERT) {
                    addSelectedPilots();
                    ke.consume();
                } else if (ke.getKeyCode() == KeyEvent.VK_DELETE) {
                    removeSelectedPilots();
                    ke.consume();
                }
            }
        });
    }

    private void addSelectedPilots() {
        applySelectedPilots(true);
    }

    private void removeSelectedPilots() {
        applySelectedPilots(false);
    }

    private void applySelectedPilots(boolean action) {
        int[] selected = table.getSelectedRows();
        for (int i = 0; i < selected.length; i++) {
            selected[i] = table.convertRowIndexToModel(selected[i]);
        }

        List<Pilot> rows = new ArrayList<Pilot>(selected.length);
        for (int mRow : selected) {
            rows.add(model.getValueAt(mRow));
        }

        if (!rows.isEmpty()) {
            applyRows(rows, action);

            // It's very important for resorting that no other rows
            // have been modified when firing individual updates
            for (int i = 0; i < selected.length; i++) {
                applyAttendee(rows.get(i), currentEvent, action);
                model.fireTableCellUpdated(selected[i], 0);
            }
        }
    }

    private void applyAttendee(Pilot pilot, Event event, boolean action) {
        if (action) {
            pilot.getEvents().add(event);
        } else {
            pilot.getEvents().remove(event);
        }
    }

    private void applyRows(List<Pilot> rows, boolean action) {
        assert (SwingUtilities.isEventDispatchThread());

        Pilot item = null;
        win.getDatabase().startSession();
        try {
            DatabaseSession.begin();

            for (Pilot row : rows) {
                item = row;

                row = pilotDAO.get(row);
                applyAttendee(row, currentEvent, action);
                pilotDAO.persist(row);
            }

            DatabaseSession.commit();
        } catch (PersistenceException e) {
            if (item != null) {
                log.error(
                        String.format("Unable to update row: row=%s#%d", Pilot.class.getSimpleName(), item.getId()), //$NON-NLS-1$
                        e);
            }
            win.reloadCurrentTabs();
            DatabaseError.errorSaving(win.getFrame(), Constants.APP_NAME, e);
        } finally {
            win.getDatabase().endSession();
        }
    }

    @Override
    @SuppressWarnings("unused")
    public void tabRefresh(Event event) {
        assert (Background.isExecutorThread());

        final Event newEvent;
        final List<Pilot> newPilots;

        win.getDatabase().startSession();
        try {
            DatabaseSession.begin();

            newEvent = eventDAO.get(event);
            for (Race race : newEvent.getRaces()) {
                ;
            }
            newPilots = new ArrayList<Pilot>(newEvent.getSeries().getPilots());
            for (Pilot pilot : newPilots) {
                for (RaceNumber raceNumber : pilot.getRaceNumbers()) {
                    ;
                }
                for (Event event_ : pilot.getEvents()) {
                    ;
                }
                for (Race race : pilot.getRaces().keySet()) {
                    ;
                }
            }
            DatabaseSession.commit();

            eventDAO.detach(event);
        } finally {
            win.getDatabase().endSession();
        }

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                if (!Objects.equal(currentEvent, newEvent)) {
                    model.updateModel(Collections.<Pilot>emptyList());
                }
                currentEvent = newEvent;
                model.updateModel(newPilots);
            }
        });
    }

    @Override
    public void tabClear() {
        assert (Background.isExecutorThread());

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                model.updateModel(Collections.<Pilot>emptyList());
                currentEvent = null;
            }
        });
    }
}