package org.limewire.ui.swing.downloads; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import org.limewire.collection.glazedlists.GlazedListsFactory; import org.limewire.core.api.download.DownloadItem; import org.limewire.core.api.download.DownloadListManager; import org.limewire.core.api.download.DownloadState; import org.limewire.inject.LazySingleton; import org.limewire.ui.swing.downloads.table.DownloadStateExcluder; import org.limewire.util.FileUtils; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.SortedList; import com.google.inject.Inject; @LazySingleton public class DownloadMediator { public static enum SortOrder {ORDER_ADDED, NAME, PROGRESS, TIME_REMAINING, SPEED, STATUS, FILE_TYPE, EXTENSION}; /** * unfiltered - common to all tables */ private final SortedList<DownloadItem> commonBaseList; private DownloadListManager downloadListManager; private boolean isAscending = true; private SortOrder sortOrder = SortOrder.ORDER_ADDED; @Inject public DownloadMediator(DownloadListManager downloadManager) { this.downloadListManager = downloadManager; EventList<DownloadItem> baseList = GlazedListsFactory.filterList(downloadManager.getSwingThreadSafeDownloads(), new DownloadStateExcluder(DownloadState.CANCELLED)); commonBaseList = GlazedListsFactory.sortedList(baseList, new DescendingComparator(new OrderAddedComparator())); } public boolean isSortAscending() { return isAscending; } public SortOrder getSortOrder() { return sortOrder; } public void setSortOrder(SortOrder order, boolean isAscending){ this.isAscending = isAscending; this.sortOrder = order; Comparator<DownloadItem> comparator; switch (order) { case ORDER_ADDED: comparator = new OrderAddedComparator(); break; case NAME: comparator = new NameComparator(); break; case PROGRESS: comparator = new ProgressComparator(); break; case TIME_REMAINING: comparator = new TimeRemainingComparator(); break; case SPEED: comparator = new SpeedComparator(); break; case STATUS: comparator = new StateComparator(); break; case FILE_TYPE: comparator = new FileTypeComparator(); break; case EXTENSION: comparator = new FileExtensionComparator(); break; default: throw new IllegalArgumentException("Unknown SortOrder: " + order); } if(isAscending){ commonBaseList.setComparator(comparator); } else { commonBaseList.setComparator(new DescendingComparator(comparator)); } } public void pauseAll() { commonBaseList.getReadWriteLock().writeLock().lock(); try { for (DownloadItem item : commonBaseList) { if (item.getState().isPausable()) { item.pause(); } } } finally { commonBaseList.getReadWriteLock().writeLock().unlock(); } } public void resumeAll() { commonBaseList.getReadWriteLock().writeLock().lock(); try { for (DownloadItem item : commonBaseList) { if (item.getState().isResumable()) { item.resume(); } } } finally { commonBaseList.getReadWriteLock().writeLock().unlock(); } } public EventList<DownloadItem> getDownloadList() { return this.commonBaseList; } public void clearFinished() { downloadListManager.clearFinished(); } public void fixStalled() { List<DownloadItem> items = getMatchingDownloadItems(DownloadState.STALLED); for (DownloadItem item : items) { item.resume(); } } public void cancelStalled() { cancelMatchingDownloadItems(DownloadState.STALLED); } public void cancelError() { cancelMatchingDownloadItems(DownloadState.ERROR); } public void cancelAll() { cancelMatchingDownloadItems(null); } public boolean hasResumable() { commonBaseList.getReadWriteLock().writeLock().lock(); try { for (DownloadItem item : commonBaseList) { if(item.getState().isResumable()) return true; } } finally { commonBaseList.getReadWriteLock().writeLock().unlock(); } return false; } public boolean hasPausable() { commonBaseList.getReadWriteLock().writeLock().lock(); try { for (DownloadItem item : commonBaseList) { if(item.getState().isPausable()) return true; } } finally { commonBaseList.getReadWriteLock().writeLock().unlock(); } return false; } public boolean containsState(DownloadState state) { return getMatchingDownloadItems(state).size() > 0; } /** * * @param state The state of the DownloadItems to be canceled. Null will cancel all. */ private void cancelMatchingDownloadItems(DownloadState state){ List<DownloadItem> items = getMatchingDownloadItems(state); for(DownloadItem item : items){ item.cancel(); } } /** * * @param state null will return all DownloadItems * @return a List of all DownloadItems in the specified DownloadState */ private List<DownloadItem> getMatchingDownloadItems(DownloadState state) { if (state == null) { return new ArrayList<DownloadItem>(commonBaseList); } List<DownloadItem> matchingItems = new ArrayList<DownloadItem>(); for (DownloadItem item : commonBaseList) { if (item.getState() == state) { matchingItems.add(item); } } return matchingItems; } private static class StateComparator implements Comparator<DownloadItem>{ @Override public int compare(DownloadItem o1, DownloadItem o2) { if (o1 == o2){ return 0; } return getSortPriority(o1.getState()) - getSortPriority(o2.getState()); } private int getSortPriority(DownloadState state){ switch(state){ case DONE: return 1; case FINISHING: return 2; case DOWNLOADING: return 3; case RESUMING: return 4; case CONNECTING: return 5; case PAUSED: return 6; case REMOTE_QUEUED: return 7; case LOCAL_QUEUED: return 8; case TRYING_AGAIN: return 9; case STALLED: return 10; case ERROR: return 11; case CANCELLED: return 12; } throw new IllegalArgumentException("Unknown DownloadState: " + state); } } private static class OrderAddedComparator implements Comparator<DownloadItem>{ @Override public int compare(DownloadItem o1, DownloadItem o2) { if (o1 == o2){ return 0; } return o2.getStartDate().compareTo(o1.getStartDate()); } } private static class NameComparator implements Comparator<DownloadItem>{ @Override public int compare(DownloadItem o1, DownloadItem o2) { if (o1 == o2){ return 0; } return o1.getTitle().compareTo(o2.getTitle()); } } private static class ProgressComparator implements Comparator<DownloadItem>{ @Override public int compare(DownloadItem o1, DownloadItem o2) { if (o1 == o2){ return 0; } return o1.getPercentComplete() - o2.getPercentComplete(); } } private static class TimeRemainingComparator implements Comparator<DownloadItem>{ @Override public int compare(DownloadItem o1, DownloadItem o2) { if (o1 == o2){ return 0; } return (int)(o1.getRemainingDownloadTime() - o2.getRemainingDownloadTime()); } } private static class SpeedComparator implements Comparator<DownloadItem>{ @Override public int compare(DownloadItem o1, DownloadItem o2) { if (o1 == o2){ return 0; } return (int)o2.getDownloadSpeed() - (int)o1.getDownloadSpeed(); } } private static class FileTypeComparator implements Comparator<DownloadItem>{ @Override public int compare(DownloadItem o1, DownloadItem o2) { if (o1 == o2){ return 0; } return o1.getCategory().compareTo(o2.getCategory()); } } private static class FileExtensionComparator implements Comparator<DownloadItem> { @Override public int compare(DownloadItem o1, DownloadItem o2) { if (o1 == o2){ return 0; } return FileUtils.getFileExtension(o1.getDownloadingFile()).compareTo(FileUtils.getFileExtension(o2.getDownloadingFile())); } } private static class DescendingComparator implements Comparator<DownloadItem>{ private Comparator<DownloadItem> delegate; public DescendingComparator(Comparator<DownloadItem> delegate){ this.delegate = delegate; } @Override public int compare(DownloadItem o1, DownloadItem o2) { return -1 * delegate.compare(o1, o2); } } }