1 /****************************************************************************************
2 * Copyright (c) 2007 Nikolaj Hald Nielsen <nhn@kde.org> *
3 * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify it under *
6 * the terms of the GNU General Public License as published by the Free Software *
7 * Foundation; either version 2 of the License, or (at your option) any later *
8 * version. *
9 * *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY *
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
12 * PARTICULAR PURPOSE. See the GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License along with *
15 * this program. If not, see <http://www.gnu.org/licenses/>. *
16 ****************************************************************************************/
17
18 #include "MemoryMatcher.h"
19
20 using namespace Meta;
21
MemoryMatcher()22 MemoryMatcher::MemoryMatcher()
23 : m_next( 0 )
24 {
25 }
26
~MemoryMatcher()27 MemoryMatcher::~MemoryMatcher()
28 {
29 delete m_next;
30 }
31
32 bool
isLast() const33 MemoryMatcher::isLast() const
34 {
35 return !m_next;
36 }
37
38 MemoryMatcher*
next() const39 MemoryMatcher::next() const
40 {
41 return m_next;
42 }
43
44 void
setNext(MemoryMatcher * next)45 MemoryMatcher::setNext( MemoryMatcher *next )
46 {
47 delete m_next;
48 m_next = next;
49 }
50
TrackMatcher(const TrackPtr & track)51 TrackMatcher::TrackMatcher( const TrackPtr &track )
52 : MemoryMatcher()
53 , m_track( track )
54 {}
55
match(Collections::MemoryCollection * memColl)56 TrackList TrackMatcher::match( Collections::MemoryCollection *memColl )
57 {
58 if( !m_track || !memColl )
59 return TrackList();
60 TrackMap trackMap = memColl->trackMap();
61 TrackList result;
62 if ( trackMap.contains( m_track->uidUrl() ) )
63 result.append( trackMap.value( m_track->uidUrl() ) );
64 return result; //checking for another matcher is not necessary
65 }
66
match(const TrackList & tracks)67 TrackList TrackMatcher::match( const TrackList &tracks )
68 {
69 if( !m_track )
70 return TrackList();
71 TrackList result;
72 QString url = m_track->uidUrl();
73 foreach( TrackPtr track, tracks )
74 if ( track->uidUrl() == url )
75 {
76 result.append( track );
77 break;
78 }
79 return result; //checking for another matcher is not necessary
80 }
81
82
83
ArtistMatcher(const ArtistPtr & artist,Collections::QueryMaker::ArtistMatchBehaviour artistMode)84 ArtistMatcher::ArtistMatcher( const ArtistPtr &artist, Collections::QueryMaker::ArtistMatchBehaviour artistMode )
85 : MemoryMatcher()
86 , m_artist( artist )
87 , m_queryMode( artistMode )
88 {}
89
match(Collections::MemoryCollection * memColl)90 TrackList ArtistMatcher::match( Collections::MemoryCollection *memColl )
91 {
92 if( !m_artist || !memColl )
93 return TrackList();
94
95 if( !memColl->artistMap().contains( m_artist->name() ) )
96 return TrackList();
97
98 ArtistPtr artist = memColl->artistMap().value( m_artist->name() );
99
100 TrackList matchingTracks;
101 switch( m_queryMode )
102 {
103 case Collections::QueryMaker::AlbumOrTrackArtists:
104 case Collections::QueryMaker::AlbumArtists:
105 foreach( AlbumPtr album, memColl->albumMap() )
106 if( album->albumArtist() == artist )
107 matchingTracks.append( album->tracks() );
108 if( m_queryMode != Collections::QueryMaker::AlbumOrTrackArtists )
109 break;
110 Q_FALLTHROUGH();
111 case Collections::QueryMaker::TrackArtists:
112 matchingTracks.append( artist->tracks() );
113 }
114
115 if( isLast() || matchingTracks.isEmpty() )
116 return matchingTracks;
117 else
118 return next()->match( matchingTracks );
119 }
120
121
match(const TrackList & tracks)122 TrackList ArtistMatcher::match( const TrackList &tracks )
123 {
124 if( !m_artist )
125 return TrackList();
126 TrackList matchingTracks;
127 QString name = m_artist->name();
128 foreach( TrackPtr track, tracks )
129 switch( m_queryMode )
130 {
131 case Collections::QueryMaker::AlbumOrTrackArtists:
132 case Collections::QueryMaker::AlbumArtists:
133 if( track->album()->hasAlbumArtist() &&
134 track->album()->albumArtist()->name() == name )
135 matchingTracks.append( track );
136 if( m_queryMode != Collections::QueryMaker::AlbumOrTrackArtists )
137 break;
138 Q_FALLTHROUGH();
139 case Collections::QueryMaker::TrackArtists:
140 if( track->artist()->name() == name )
141 matchingTracks.append( track );
142 }
143
144 if( isLast() || matchingTracks.isEmpty() )
145 return matchingTracks;
146 else
147 return next()->match( matchingTracks );
148 }
149
150
151
AlbumMatcher(const AlbumPtr & album)152 AlbumMatcher::AlbumMatcher( const AlbumPtr &album )
153 : MemoryMatcher()
154 , m_album( album )
155 {}
156
match(Collections::MemoryCollection * memColl)157 TrackList AlbumMatcher::match( Collections::MemoryCollection *memColl )
158 {
159 if( !m_album || !memColl )
160 return TrackList();
161 AlbumMap albumMap = memColl->albumMap();
162 if ( albumMap.contains( m_album ) ) // compares albums by value
163 {
164 AlbumPtr album = albumMap.value( m_album ); // compares albums by value, too
165 TrackList matchingTracks = album->tracks();
166 if ( isLast() )
167 return matchingTracks;
168 else
169 return next()->match( matchingTracks );
170 }
171 else
172 return TrackList();
173 }
174
match(const TrackList & tracks)175 TrackList AlbumMatcher::match( const TrackList &tracks )
176 {
177 if( !m_album )
178 return TrackList();
179 TrackList matchingTracks;
180 QString name = m_album->name();
181 foreach( TrackPtr track, tracks )
182 if ( track->album()->name() == name )
183 matchingTracks.append( track );
184 if ( isLast() || matchingTracks.isEmpty())
185 return matchingTracks;
186 else
187 return next()->match( matchingTracks );
188 }
189
190
191
GenreMatcher(const GenrePtr & genre)192 GenreMatcher::GenreMatcher( const GenrePtr &genre )
193 : MemoryMatcher()
194 , m_genre( genre )
195 {}
196
match(Collections::MemoryCollection * memColl)197 TrackList GenreMatcher::match( Collections::MemoryCollection *memColl )
198 {
199 if( !m_genre || !memColl )
200 return TrackList();
201 GenreMap genreMap = memColl->genreMap();
202 if ( genreMap.contains( m_genre->name() ) )
203 {
204 GenrePtr genre = genreMap.value( m_genre->name() );
205 TrackList matchingTracks = genre->tracks();
206 if ( isLast() )
207 return matchingTracks;
208 else
209 return next()->match( matchingTracks );
210 }
211 else
212 return TrackList();
213 }
214
match(const TrackList & tracks)215 TrackList GenreMatcher::match( const TrackList &tracks )
216 {
217 if( !m_genre )
218 return TrackList();
219 TrackList matchingTracks;
220 QString name = m_genre->name();
221 foreach( TrackPtr track, tracks )
222 if ( track->genre()->name() == name )
223 matchingTracks.append( track );
224 if ( isLast() || matchingTracks.isEmpty())
225 return matchingTracks;
226 else
227 return next()->match( matchingTracks );
228 }
229
230
231
ComposerMatcher(const ComposerPtr & composer)232 ComposerMatcher::ComposerMatcher( const ComposerPtr &composer )
233 : MemoryMatcher()
234 , m_composer( composer )
235 {}
236
match(Collections::MemoryCollection * memColl)237 TrackList ComposerMatcher::match( Collections::MemoryCollection *memColl )
238 {
239 if( !m_composer || !memColl )
240 return TrackList();
241 ComposerMap composerMap = memColl->composerMap();
242 if ( composerMap.contains( m_composer->name() ) )
243 {
244 ComposerPtr composer = composerMap.value( m_composer->name() );
245 TrackList matchingTracks = composer->tracks();
246 if ( isLast() )
247 return matchingTracks;
248 else
249 return next()->match( matchingTracks );
250 }
251 else
252 return TrackList();
253 }
254
match(const TrackList & tracks)255 TrackList ComposerMatcher::match( const TrackList &tracks )
256 {
257 if( !m_composer )
258 return TrackList();
259 TrackList matchingTracks;
260 QString name = m_composer->name();
261 foreach( TrackPtr track, tracks )
262 if ( track->composer()->name() == name )
263 matchingTracks.append( track );
264 if ( isLast() || matchingTracks.isEmpty())
265 return matchingTracks;
266 else
267 return next()->match( matchingTracks );
268 }
269
270
271
YearMatcher(const YearPtr & year)272 YearMatcher::YearMatcher( const YearPtr &year )
273 : MemoryMatcher()
274 , m_year( year )
275 {}
276
match(Collections::MemoryCollection * memColl)277 TrackList YearMatcher::match( Collections::MemoryCollection *memColl )
278 {
279 if( !m_year || !memColl )
280 return TrackList();
281 YearMap yearMap = memColl->yearMap();
282 if ( yearMap.contains( m_year->year() ) )
283 {
284 YearPtr year = yearMap.value( m_year->year() );
285 TrackList matchingTracks = year->tracks();
286 if ( isLast() )
287 return matchingTracks;
288 else
289 return next()->match( matchingTracks );
290 }
291 else
292 return TrackList();
293 }
294
match(const TrackList & tracks)295 TrackList YearMatcher::match( const TrackList &tracks )
296 {
297 if( !m_year )
298 return TrackList();
299 TrackList matchingTracks;
300 int year = m_year->year();
301 foreach( TrackPtr track, tracks )
302 if ( track->year()->year() == year )
303 matchingTracks.append( track );
304 if ( isLast() || matchingTracks.isEmpty())
305 return matchingTracks;
306 else
307 return next()->match( matchingTracks );
308 }
309
LabelMatcher(const Meta::LabelPtr & label)310 LabelMatcher::LabelMatcher( const Meta::LabelPtr &label )
311 : MemoryMatcher()
312 , m_label( label )
313 {
314 //nothing to do
315 }
316
317 Meta::TrackList
match(const Meta::TrackList & tracks)318 LabelMatcher::match( const Meta::TrackList &tracks )
319 {
320 if( !m_label )
321 return Meta::TrackList();
322
323 Meta::TrackList matchingTracks;
324 QString name = m_label->name();
325 //not really efficient...
326 foreach( const Meta::TrackPtr &track, tracks )
327 {
328 foreach( const Meta::LabelPtr &label, track->labels() )
329 {
330 if( name == label->name() )
331 {
332 matchingTracks << track;
333 break;
334 }
335 }
336 }
337 if( isLast() || matchingTracks.isEmpty() )
338 return matchingTracks;
339 else
340 return next()->match( matchingTracks );
341 }
342
343 Meta::TrackList
match(Collections::MemoryCollection * memColl)344 LabelMatcher::match( Collections::MemoryCollection *memColl )
345 {
346 if( !m_label )
347 return Meta::TrackList();
348
349 Meta::TrackList matchingTracks;
350
351 if( memColl->labelMap().contains( m_label->name() ) )
352 {
353 //m_label might actually be a proxy label
354 Meta::LabelPtr realLabel = memColl->labelMap().value( m_label->name() );
355 matchingTracks = memColl->labelToTrackMap().value( realLabel );
356 }
357 if( isLast() || matchingTracks.isEmpty() )
358 return matchingTracks;
359 else
360 return next()->match( matchingTracks );
361 }
362
363
364
365
366
367