View Javadoc

1   /***
2    *     Ambient - A music player for the Android platform
3    Copyright (C) 2007 Martin Vysny
4    
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9    
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14  
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package sk.baka.ambient.activity.main.cb;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collections;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Set;
27  import java.util.concurrent.CopyOnWriteArrayList;
28  
29  import sk.baka.ambient.AmbientApplication;
30  import sk.baka.ambient.R;
31  import sk.baka.ambient.collection.CategoryEnum;
32  import sk.baka.ambient.collection.CategoryItem;
33  import sk.baka.ambient.collection.CollectionException;
34  import sk.baka.ambient.collection.CollectionUtils;
35  import sk.baka.ambient.collection.ICollection;
36  import sk.baka.ambient.collection.TrackMetadataBean;
37  import sk.baka.ambient.commons.Interval;
38  
39  /***
40   * Performs the criteria selection.
41   * 
42   * @author Martin Vysny
43   */
44  final class CategoryManager implements IContentManager {
45  	/***
46  	 * Browse through these categories. First item in the list is the category
47  	 * currently being browsed.
48  	 */
49  	private final List<CategoryEnum> categoriesToShow;
50  
51  	/***
52  	 * The parent category to display the data from. May be <code>null</code>
53  	 * if no category item has yet been selected.
54  	 */
55  	private final CategoryItem parent;
56  
57  	/***
58  	 * Previous category manager. If <code>null</code> then
59  	 * {@link GroupingManager} is the previous one.
60  	 */
61  	private final CategoryManager previous;
62  
63  	/***
64  	 * Creates new manager.
65  	 * 
66  	 * @param categories
67  	 *            browse through these categories.
68  	 */
69  	CategoryManager(final CategoryEnum[] categories) {
70  		super();
71  		this.categoriesToShow = Arrays.asList(categories);
72  		previous = null;
73  		parent = null;
74  	}
75  
76  	/***
77  	 * Creates new manager.
78  	 * 
79  	 * @param previous
80  	 *            Previous category manager. If <code>null</code> then
81  	 *            {@link GroupingManager} is the previous one.
82  	 * @param parent
83  	 *            The parent category to display the data from. May be
84  	 *            <code>null</code> if no category item has yet been selected.
85  	 * @param categoriesToShow
86  	 *            Browse through these categories. First item in the list is the
87  	 *            category currently being browsed.
88  	 */
89  	private CategoryManager(final CategoryManager previous,
90  			final CategoryItem parent, final List<CategoryEnum> categoriesToShow) {
91  		super();
92  		this.categoriesToShow = categoriesToShow;
93  		this.previous = previous;
94  		this.parent = parent;
95  	}
96  
97  	public boolean canReturnTracks() {
98  		return true;
99  	}
100 
101 	public List<String> getDisplayableContent() {
102 		return displayableCategoriesShown;
103 	}
104 
105 	/***
106 	 * The manager is currently showing these categories.
107 	 */
108 	private volatile List<CategoryItem> categoriesShown;
109 
110 	/***
111 	 * The manager is currently showing these categories.
112 	 */
113 	private volatile List<String> displayableCategoriesShown;
114 
115 	public List<TrackMetadataBean> getTracks(Interval highlight)
116 			throws CollectionException, InterruptedException {
117 		// if multiple genres are selected, we may need to filter out
118 		// multiple track instances
119 		final Set<TrackMetadataBean> presentTracks = new HashSet<TrackMetadataBean>();
120 		final List<TrackMetadataBean> result = new ArrayList<TrackMetadataBean>();
121 		final List<CategoryItem> categories = categoriesShown.subList(
122 				highlight.start, highlight.end + 1);
123 		for (final CategoryItem ci : categories) {
124 			if (Thread.currentThread().isInterrupted()) {
125 				return null;
126 			}
127 			final List<TrackMetadataBean> tracks = collection.getTracks(ci);
128 			tracks.removeAll(presentTracks);
129 			presentTracks.addAll(tracks);
130 			result.addAll(tracks);
131 		}
132 		CollectionUtils.sortByAlbumOrder(result);
133 		return result;
134 	}
135 
136 	public void uninitialize() {
137 		categoriesShown = null;
138 		displayableCategoriesShown = null;
139 	}
140 
141 	public IContentManager goBack() {
142 		if (previous != null) {
143 			return previous;
144 		}
145 		return new GroupingManager();
146 	}
147 
148 	private volatile ICollection collection;
149 
150 	private volatile boolean isYear = false;
151 
152 	public boolean initialize(boolean isYear, final ICollection collection)
153 			throws CollectionException, InterruptedException {
154 		previouslyActivated = null;
155 		if ((categoriesShown != null) && (getCurrent() != CategoryEnum.Album)) {
156 			return false;
157 		}
158 		this.isYear = isYear;
159 		this.collection = collection;
160 		final List<CategoryItem> list = collection.getCategoryList(
161 				getCurrent(), parent, null, isYear);
162 		categoriesShown = new CopyOnWriteArrayList<CategoryItem>(list);
163 		final boolean albumYear = isYear
164 				&& (getCurrent() == CategoryEnum.Album);
165 		final List<String> displayableList = new ArrayList<String>();
166 		for (final CategoryItem item : list) {
167 			final String caption = albumYear ? item.getDisplayableYear() + "-"
168 					+ item.getDisplayableName() : item.getDisplayableName();
169 			displayableList.add(caption);
170 		}
171 		displayableCategoriesShown = Collections
172 				.unmodifiableList(new CopyOnWriteArrayList<String>(
173 						displayableList));
174 		return true;
175 	}
176 
177 	private CategoryItem previouslyActivated;
178 
179 	public IContentManager itemActivated(int i) {
180 		previouslyActivated = categoriesShown.get(i);
181 		if (categoriesToShow.size() > 1) {
182 			final CategoryManager clone = new CategoryManager(previous, parent,
183 					categoriesToShow);
184 			return new CategoryManager(clone, previouslyActivated,
185 					categoriesToShow.subList(1, categoriesToShow.size()));
186 		}
187 		return new TrackManager(this, previouslyActivated);
188 	}
189 
190 	/***
191 	 * Returns currently shown category.
192 	 * 
193 	 * @return the category being currently shown.
194 	 */
195 	public CategoryEnum getCurrent() {
196 		return categoriesToShow.get(0);
197 	}
198 
199 	public int getIndexOfPreviouslyActivatedItem(IContentManager contentManager) {
200 		final CategoryItem prev = ((CategoryManager) contentManager).previouslyActivated;
201 		return categoriesShown.indexOf(prev);
202 	}
203 
204 	public String getSelectedItemName() {
205 		if (previouslyActivated != null) {
206 			return previouslyActivated.getDisplayableName();
207 		}
208 		final CategoryEnum cat = getCurrent();
209 		final StringBuilder builder = new StringBuilder();
210 		if ((cat == CategoryEnum.Album) && isYear) {
211 			builder.append(AmbientApplication.getInstance().getString(
212 					R.string.year));
213 			builder.append('-');
214 		}
215 		builder.append(AmbientApplication.getInstance().getString(
216 				cat.displayableNameId));
217 		return builder.toString();
218 	}
219 }