1 /*
2  * aTunes
3  * Copyright (C) Alex Aranda, Sylvain Gaudard and contributors
4  *
5  * See http://www.atunes.org/wiki/index.php?title=Contributing for information about contributors
6  *
7  * http://www.atunes.org
8  * http://sourceforge.net/projects/atunes
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  */
20 
21 package net.sourceforge.atunes.kernel.modules.favorites;
22 
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28 
29 import org.apache.commons.collections.list.SetUniqueList;
30 
31 import net.sourceforge.atunes.kernel.modules.webservices.AddLovedSongBackgroundWorker;
32 import net.sourceforge.atunes.kernel.modules.webservices.RemoveLovedSongBackgroundWorker;
33 import net.sourceforge.atunes.model.IAudioObject;
34 import net.sourceforge.atunes.model.IBeanFactory;
35 import net.sourceforge.atunes.model.IFavorites;
36 import net.sourceforge.atunes.model.ILocalAudioObject;
37 import net.sourceforge.atunes.model.IRepositoryHandler;
38 import net.sourceforge.atunes.model.IStateContext;
39 import net.sourceforge.atunes.model.IUnknownObjectChecker;
40 import net.sourceforge.atunes.utils.CollectionUtils;
41 
42 /**
43  * Manages favorite songs
44  *
45  * @author alex
46  *
47  */
48 public class FavoritesSongsManager {
49 
50 	private IStateContext stateContext;
51 
52 	private IBeanFactory beanFactory;
53 
54 	private IRepositoryHandler repositoryHandler;
55 
56 	private IUnknownObjectChecker unknownObjectChecker;
57 
58 	/**
59 	 * @param unknownObjectChecker
60 	 */
setUnknownObjectChecker( final IUnknownObjectChecker unknownObjectChecker)61 	public void setUnknownObjectChecker(
62 			final IUnknownObjectChecker unknownObjectChecker) {
63 		this.unknownObjectChecker = unknownObjectChecker;
64 	}
65 
66 	/**
67 	 * @param repositoryHandler
68 	 */
setRepositoryHandler(final IRepositoryHandler repositoryHandler)69 	public void setRepositoryHandler(final IRepositoryHandler repositoryHandler) {
70 		this.repositoryHandler = repositoryHandler;
71 	}
72 
73 	/**
74 	 * @param beanFactory
75 	 */
setBeanFactory(final IBeanFactory beanFactory)76 	public void setBeanFactory(final IBeanFactory beanFactory) {
77 		this.beanFactory = beanFactory;
78 	}
79 
80 	/**
81 	 * @param stateContext
82 	 */
setStateContext(final IStateContext stateContext)83 	public void setStateContext(final IStateContext stateContext) {
84 		this.stateContext = stateContext;
85 	}
86 
87 	/**
88 	 * Adds favorite songs
89 	 *
90 	 * @param favorites
91 	 * @param songs
92 	 * @param updateWebServices
93 	 * @return true if favorites have changed
94 	 */
addSongs(final IFavorites favorites, final Collection<ILocalAudioObject> songs, final boolean updateWebServices)95 	public boolean addSongs(final IFavorites favorites,
96 			final Collection<ILocalAudioObject> songs,
97 			final boolean updateWebServices) {
98 		if (CollectionUtils.isEmpty(songs)) {
99 			return false;
100 		}
101 
102 		for (ILocalAudioObject song : songs) {
103 			favorites.addSong(song);
104 		}
105 
106 		if (updateWebServices && this.stateContext.isLastFmEnabled()
107 				&& this.stateContext.isAutoLoveFavoriteSong()) {
108 			this.beanFactory.getBean(AddLovedSongBackgroundWorker.class).add(
109 					new ArrayList<IAudioObject>(songs));
110 		}
111 
112 		return true;
113 	}
114 
115 	/**
116 	 * Remove favorite songs
117 	 *
118 	 * @param favorites
119 	 * @param songs
120 	 * @param updateWebServices
121 	 * @return true if favorites have changed
122 	 */
removeSongs(final IFavorites favorites, final Collection<ILocalAudioObject> songs, final boolean updateWebServices)123 	public boolean removeSongs(final IFavorites favorites,
124 			final Collection<ILocalAudioObject> songs,
125 			final boolean updateWebServices) {
126 		if (CollectionUtils.isEmpty(songs)) {
127 			return false;
128 		}
129 
130 		for (ILocalAudioObject file : songs) {
131 			favorites.removeSong(file);
132 		}
133 
134 		if (updateWebServices && this.stateContext.isLastFmEnabled()
135 				&& this.stateContext.isAutoLoveFavoriteSong()) {
136 			this.beanFactory.getBean(RemoveLovedSongBackgroundWorker.class)
137 					.remove(new ArrayList<IAudioObject>(songs));
138 		}
139 
140 		return true;
141 	}
142 
143 	/**
144 	 * Takes songs from a list of audio objects and add or remove songs from
145 	 * favorites
146 	 *
147 	 * @param favorites
148 	 * @param songs
149 	 * @return if favorites have changed
150 	 */
toggleFavoriteSongs(final IFavorites favorites, final List<ILocalAudioObject> songs)151 	public boolean toggleFavoriteSongs(final IFavorites favorites,
152 			final List<ILocalAudioObject> songs) {
153 		if (CollectionUtils.isEmpty(songs)) {
154 			return false;
155 		}
156 
157 		@SuppressWarnings("unchecked")
158 		Set<ILocalAudioObject> set = SetUniqueList.decorate(songs).asSet();
159 
160 		Set<ILocalAudioObject> toAdd = new HashSet<ILocalAudioObject>();
161 		Set<ILocalAudioObject> toRemove = new HashSet<ILocalAudioObject>();
162 		for (ILocalAudioObject song : set) {
163 			// Toggle favorite songs
164 			if (favorites.containsSong(song)) {
165 				toRemove.add(song);
166 			} else {
167 				toAdd.add(song);
168 			}
169 		}
170 
171 		addSongs(favorites, toAdd, true);
172 		removeSongs(favorites, toRemove, true);
173 
174 		return !toAdd.isEmpty() || !toRemove.isEmpty();
175 	}
176 
177 	/**
178 	 * Checks all songs to see if exists in repository, removing if does not
179 	 * exist
180 	 *
181 	 * @param favorites
182 	 * @return true if favorites changed
183 	 */
checkFavoriteSongs(final IFavorites favorites)184 	public boolean checkFavoriteSongs(final IFavorites favorites) {
185 		List<ILocalAudioObject> toRemove = new ArrayList<ILocalAudioObject>();
186 		for (ILocalAudioObject favorite : favorites.getFavoriteSongs()) {
187 			if (!this.repositoryHandler.existsFile(favorite)) {
188 				toRemove.add(favorite);
189 			}
190 		}
191 		return removeSongs(favorites, toRemove, false);
192 	}
193 
194 	/**
195 	 * @param favorites
196 	 * @param artist
197 	 * @param title
198 	 * @return true if a song with given artist and title is favorite
199 	 */
isSongFavorite(final IFavorites favorites, final String artist, final String title)200 	public boolean isSongFavorite(final IFavorites favorites,
201 			final String artist, final String title) {
202 		// TODO: This method checks all favorite songs to find one matching
203 		// With favorites stored by metadata this would not be necessary
204 		for (ILocalAudioObject ao : favorites.getFavoriteSongs()) {
205 			if (ao.getArtist(this.unknownObjectChecker)
206 					.equalsIgnoreCase(artist)
207 					&& title.equalsIgnoreCase(ao.getTitle())) {
208 				return true;
209 			}
210 		}
211 		return false;
212 	}
213 }
214