package org.limewire.ui.swing.filter; import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; import java.util.List; import java.util.Map; import org.limewire.core.api.FilePropertyKey; import org.limewire.core.api.search.SearchCategory; import org.limewire.ui.swing.components.Disposable; import org.limewire.ui.swing.util.IconManager; import com.google.inject.Provider; /** * A manager for filters. FilterManager maintains a set of filters that can be * applied to a filterable data source. A variety of filter types are * supported. Filters are internally cached within the manager for reuse by * different search categories. When a search category is selected, the * <code>getPropertyFilterList()</code> method returns a list of the available * filters for the category. */ public class FilterManager<E extends FilterableItem> implements Disposable { /** Filterable data source. */ private final FilterableSource<E> filterableSource; /** Icon manager for determining file types. */ private final Provider<IconManager> iconManager; /** Map containing non-property filters. */ private final Map<FilterType, Filter<E>> filterMap = new EnumMap<FilterType, Filter<E>>(FilterType.class); /** Map containing property filters. */ private final Map<FilePropertyKey, Filter<E>> propertyFilterMap = new EnumMap<FilePropertyKey, Filter<E>>(FilePropertyKey.class); /** * Constructs a FilterManager using the specified filterable data source * and icon manager. */ public FilterManager(FilterableSource<E> filterableSource, Provider<IconManager> iconManager) { this.filterableSource = filterableSource; this.iconManager = iconManager; } @Override public void dispose() { // Dispose of all non-property filters. Collection<Filter<E>> filters = filterMap.values(); for (Filter<E> filter : filters) { filter.dispose(); } // Dispose of all property filters. Collection<Filter<E>> propertyFilters = propertyFilterMap.values(); for (Filter<E> filter : propertyFilters) { filter.dispose(); } } /** * Returns a list of all available filters. */ public List<Filter<E>> getFiltersInUse() { List<Filter<E>> filterList = new ArrayList<Filter<E>>(); // Add all non-property filters. filterList.addAll(filterMap.values()); // Add all property filters. filterList.addAll(propertyFilterMap.values()); return filterList; } /** * Returns a filter for file categories. */ public CategoryFilter<E> getCategoryFilter() { return (CategoryFilter<E>) getFilter(FilterType.CATEGORY); } /** * Returns a filter for file sources. */ public SourceFilter<E> getSourceFilter() { return (SourceFilter<E>) getFilter(FilterType.SOURCE); } /** * Returns the minimum number of property filters for the specified filter * category. A value less than 1 means that there is no minimum and all * filters are displayed. */ public int getPropertyFilterMinimum(SearchCategory filterCategory) { return (filterCategory == SearchCategory.AUDIO) ? 3 : -1; } /** * Returns a list of filters for the specified filter category. */ public List<Filter<E>> getPropertyFilterList(SearchCategory filterCategory) { // Create filter list. List<Filter<E>> filterList = new ArrayList<Filter<E>>(); switch (filterCategory) { case AUDIO: filterList.add(getPropertyFilter(FilePropertyKey.AUTHOR)); filterList.add(getPropertyFilter(FilePropertyKey.ALBUM)); filterList.add(getPropertyFilter(FilePropertyKey.GENRE)); filterList.add(getFilter(FilterType.FILE_SIZE, filterCategory)); filterList.add(getFilter(FilterType.EXTENSION)); filterList.add(getFilter(FilterType.BIT_RATE)); filterList.add(getFilter(FilterType.LENGTH)); break; case VIDEO: filterList.add(getFilter(FilterType.FILE_SIZE, filterCategory)); filterList.add(getFilter(FilterType.EXTENSION)); filterList.add(getFilter(FilterType.QUALITY)); filterList.add(getFilter(FilterType.LENGTH)); break; case DOCUMENT: case OTHER: filterList.add(getFilter(FilterType.FILE_TYPE)); filterList.add(getFilter(FilterType.FILE_SIZE, filterCategory)); filterList.add(getFilter(FilterType.EXTENSION)); break; case ALL: case IMAGE: case PROGRAM: default: filterList.add(getFilter(FilterType.FILE_SIZE, filterCategory)); filterList.add(getFilter(FilterType.EXTENSION)); break; } return filterList; } /** * Returns the filter for the specified filter type. */ private Filter<E> getFilter(FilterType filterType) { Filter<E> filter = filterMap.get(filterType); if (filter == null) { filter = createFilter(filterType, null); filterMap.put(filterType, filter); } return filter; } /** * Returns the filter for the specified filter type and category. */ private Filter<E> getFilter(FilterType filterType, SearchCategory filterCategory) { Filter<E> filter = getFilter(filterType); // Update range in range filters. if (filter instanceof RangeFilter) { ((RangeFilter) filter).updateRange(filterCategory); } return filter; } /** * Return the property filter for the specified property key. */ private Filter<E> getPropertyFilter(FilePropertyKey propertyKey) { Filter<E> filter = propertyFilterMap.get(propertyKey); if (filter == null) { filter = createFilter(FilterType.PROPERTY, propertyKey); propertyFilterMap.put(propertyKey, filter); } return filter; } /** * Creates a new filter for the specified filter type and property key. * For FilterType.PROPERTY, <code>propertyKey</code> must be non-null. */ private Filter<E> createFilter(FilterType filterType, FilePropertyKey propertyKey) { switch (filterType) { case BIT_RATE: return new RangeFilter<E>(new BitRateFilterFormat<E>()); case CATEGORY: return new CategoryFilter<E>(filterableSource.getFilteredList()); case EXTENSION: return new PropertyFilter<E>(filterableSource.getFilteredList(), FilterType.EXTENSION, null, iconManager); case FILE_SIZE: return new RangeFilter<E>(new FileSizeFilterFormat<E>()); case FILE_TYPE: return new PropertyFilter<E>(filterableSource.getFilteredList(), FilterType.FILE_TYPE, null, iconManager); case LENGTH: return new RangeFilter<E>(new LengthFilterFormat<E>()); case PROPERTY: return new PropertyFilter<E>(filterableSource.getFilteredList(), FilterType.PROPERTY, propertyKey, iconManager); case QUALITY: return new RangeFilter<E>(new QualityFilterFormat<E>()); case SOURCE: return new SourceFilter<E>(filterableSource.getFilteredList()); default: throw new IllegalArgumentException("Invalid filter type " + filterType); } } }