package com.github.pfichtner.jrunalyser.ui.tracklist;
import java.awt.BorderLayout;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.pfichtner.jrunalyser.base.data.SegmentationUnit;
import com.github.pfichtner.jrunalyser.base.data.track.Id;
import com.github.pfichtner.jrunalyser.base.datasource.DatasourceFascade;
import com.github.pfichtner.jrunalyser.di.Inject;
import com.github.pfichtner.jrunalyser.ui.base.AbstractUiPlugin;
import com.github.pfichtner.jrunalyser.ui.base.i18n.I18N;
import com.github.pfichtner.jrunalyser.ui.dock.ebus.AdditionalTracks;
import com.github.pfichtner.jrunalyser.ui.dock.ebus.TrackAdded;
import com.github.pfichtner.jrunalyser.ui.dock.ebus.TrackLoaded;
import com.github.pfichtner.jrunalyser.ui.dock.ebus.TrackRemoved;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
public class TrackListPlugin extends AbstractUiPlugin {
private static final Logger log = LoggerFactory
.getLogger(TrackListPlugin.class);
private static final I18N i18n = I18N
.builder(TrackListPlugin.class)
.withParent(
com.github.pfichtner.jrunalyser.ui.base.UiPlugins.getI18n())
.build();
public static I18N getI18n() {
return i18n;
}
private final JPanel panel = new JPanel(new BorderLayout());
private final TrackTable table;
private DatasourceFascade dsf;
public TrackListPlugin() {
this.table = new TrackTable(new TrackTableModel());
// sort by startdate
this.table.getRowSorter()
.toggleSortOrder(TrackTableModel.COL_STARTDATE);
this.panel.add(new JScrollPane(this.table,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED));
}
@Override
public String getTitle() {
return getI18n()
.getText(
"com.github.pfichtner.jrunalyser.ui.tracklist.TrackListPlugin.title"); //$NON-NLS-1$
}
@Override
public JPanel getPanel() {
return this.panel;
}
@Inject
public void setEventBus(EventBus eventBus) {
this.table.addEventBusPoster(eventBus);
}
@Inject
public void setDatasourceFascade(final DatasourceFascade dsf)
throws IOException, InterruptedException, ExecutionException {
this.dsf = dsf;
this.table.setEnabled(false);
final Iterable<SegmentationUnit> segmentationUnits = getSegmentationUnitsFromHeader();
new SwingWorker<Void, TrackRow>() {
@Override
protected Void doInBackground() throws Exception {
final Collection<Callable<TrackRow>> callables = createCallables(
dsf.getTrackIds(), segmentationUnits);
log.debug(
"Created {} callables", Integer.valueOf(callables.size())); //$NON-NLS-1$
ExecutorCompletionService<TrackRow> scattered = scatter(callables);
log.debug("Scattered", Integer.valueOf(callables.size())); //$NON-NLS-1$
gather(scattered, callables.size());
log.debug("Gathered", Integer.valueOf(callables.size())); //$NON-NLS-1$
return null;
}
private void gather(ExecutorCompletionService<TrackRow> ecs,
int size) {
for (int i = 0; i < size; i++) {
try {
publish(ecs.take().get());
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
} catch (final ExecutionException e) {
throw Throwables.propagate(e);
}
}
}
private List<Callable<TrackRow>> createCallables(Set<Id> ids,
final Iterable<SegmentationUnit> segmentationUnits) {
List<Callable<TrackRow>> callables = Lists
.newArrayListWithCapacity(ids.size());
for (final Id id : ids) {
callables.add(new Callable<TrackRow>() {
@Override
public TrackRow call() throws Exception {
TrackRow trackRow = new TrackRow(dsf, id);
for (SegmentationUnit segmentationUnit : segmentationUnits) {
trackRow.getBestSegment(segmentationUnit);
}
return trackRow;
}
});
}
return callables;
}
private ExecutorCompletionService<TrackRow> scatter(
final Collection<Callable<TrackRow>> callables) {
final ExecutorService es = Executors.newFixedThreadPool(Runtime
.getRuntime().availableProcessors());
final ExecutorCompletionService<TrackRow> ecs = new ExecutorCompletionService<TrackRow>(
es);
for (final Callable<TrackRow> callable : callables) {
ecs.submit(callable);
}
es.shutdown();
return ecs;
}
protected void process(List<TrackRow> trackRows) {
TrackListPlugin.this.table.getModel().addRows(trackRows);
};
@Override
protected void done() {
// call get to make sure any exceptions thrown during
// doInBackground() are thrown again
try {
get();
} catch (final InterruptedException e) {
throw Throwables.propagate(e);
} catch (final ExecutionException e) {
throw Throwables.propagate(e);
} finally {
TrackListPlugin.this.table.setEnabled(true);
}
}
}.execute();
}
private Iterable<SegmentationUnit> getSegmentationUnitsFromHeader() {
List<Object> headerValues = Lists.newArrayList();
for (int i = 0; i < this.table.getColumnModel().getColumnCount(); i++) {
headerValues.add(this.table.getModel().getHeaderValue(i));
}
return Iterables.filter(headerValues, SegmentationUnit.class);
}
protected DatasourceFascade getDatasourceFascade() {
return this.dsf;
}
@Subscribe
public void addTrack(TrackAdded message) {
try {
TrackListPlugin.this.table.getModel().addRow(
new TrackRow(this.dsf, message.getTrack().getId()));
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
@Subscribe
public void removeTrack(TrackRemoved message) {
TrackListPlugin.this.table.getModel().removeRow(
message.getTrack().getId());
}
@Subscribe
public void setTrack(TrackLoaded message) throws IOException {
this.table.setTrack(message.getTrack());
}
@Subscribe
public void setAdditionalTracks(AdditionalTracks message)
throws IOException {
this.table.setAdditionalTracks(message.getTracks());
}
}