File indexing completed on 2024-05-19 04:49:17

0001 /****************************************************************************************
0002  * Copyright (c) 2007 Nikolaj Hald Nielsen <nhn@kde.org>                                *
0003  * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com>            *
0004  *                                                                                      *
0005  * This program is free software; you can redistribute it and/or modify it under        *
0006  * the terms of the GNU General Public License as published by the Free Software        *
0007  * Foundation; either version 2 of the License, or (at your option) any later           *
0008  * version.                                                                             *
0009  *                                                                                      *
0010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0012  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0013  *                                                                                      *
0014  * You should have received a copy of the GNU General Public License along with         *
0015  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0016  ****************************************************************************************/
0017 
0018 #include "MemoryMatcher.h"
0019 
0020 using namespace Meta;
0021 
0022 MemoryMatcher::MemoryMatcher()
0023     : m_next( nullptr )
0024 {
0025 }
0026 
0027 MemoryMatcher::~MemoryMatcher()
0028 {
0029     delete m_next;
0030 }
0031 
0032 bool
0033 MemoryMatcher::isLast() const
0034 {
0035     return !m_next;
0036 }
0037 
0038 MemoryMatcher*
0039 MemoryMatcher::next() const
0040 {
0041     return m_next;
0042 }
0043 
0044 void
0045 MemoryMatcher::setNext( MemoryMatcher *next )
0046 {
0047     delete m_next;
0048     m_next = next;
0049 }
0050 
0051 TrackMatcher::TrackMatcher( const TrackPtr &track )
0052     : MemoryMatcher()
0053     , m_track( track )
0054 {}
0055 
0056 TrackList TrackMatcher::match( Collections::MemoryCollection *memColl )
0057 {
0058     if( !m_track || !memColl )
0059         return TrackList();
0060     TrackMap trackMap = memColl->trackMap();
0061     TrackList result;
0062     if ( trackMap.contains( m_track->uidUrl()  ) )
0063         result.append( trackMap.value( m_track->uidUrl() ) );
0064     return result; //checking for another matcher is not necessary
0065 }
0066 
0067 TrackList TrackMatcher::match( const TrackList &tracks )
0068 {
0069     if( !m_track )
0070         return TrackList();
0071     TrackList result;
0072     QString url = m_track->uidUrl();
0073     foreach( TrackPtr track, tracks )
0074         if ( track->uidUrl() == url )
0075         {
0076             result.append( track );
0077             break;
0078         }
0079     return result; //checking for another matcher is not necessary
0080 }
0081 
0082 
0083 
0084 ArtistMatcher::ArtistMatcher( const ArtistPtr &artist, Collections::QueryMaker::ArtistMatchBehaviour artistMode )
0085     : MemoryMatcher()
0086     , m_artist( artist )
0087     , m_queryMode( artistMode )
0088 {}
0089 
0090 TrackList ArtistMatcher::match( Collections::MemoryCollection *memColl )
0091 {
0092     if( !m_artist || !memColl )
0093         return TrackList();
0094 
0095     if( !memColl->artistMap().contains( m_artist->name() ) )
0096         return TrackList();
0097 
0098     ArtistPtr artist = memColl->artistMap().value( m_artist->name() );
0099 
0100     TrackList matchingTracks;
0101     switch( m_queryMode )
0102     {
0103         case Collections::QueryMaker::AlbumOrTrackArtists:
0104         case Collections::QueryMaker::AlbumArtists:
0105             foreach( AlbumPtr album, memColl->albumMap() )
0106                 if( album->albumArtist() == artist )
0107                     matchingTracks.append( album->tracks() );
0108             if( m_queryMode != Collections::QueryMaker::AlbumOrTrackArtists )
0109                 break;
0110             Q_FALLTHROUGH();
0111         case Collections::QueryMaker::TrackArtists:
0112             matchingTracks.append( artist->tracks() );
0113     }
0114 
0115     if( isLast() || matchingTracks.isEmpty() )
0116         return matchingTracks;
0117     else
0118         return next()->match( matchingTracks );
0119 }
0120 
0121 
0122 TrackList ArtistMatcher::match( const TrackList &tracks )
0123 {
0124     if( !m_artist )
0125         return TrackList();
0126     TrackList matchingTracks;
0127     QString name = m_artist->name();
0128     foreach( TrackPtr track, tracks )
0129         switch( m_queryMode )
0130         {
0131             case Collections::QueryMaker::AlbumOrTrackArtists:
0132             case Collections::QueryMaker::AlbumArtists:
0133                 if( track->album()->hasAlbumArtist() &&
0134                     track->album()->albumArtist()->name() == name )
0135                     matchingTracks.append( track );
0136                 if( m_queryMode != Collections::QueryMaker::AlbumOrTrackArtists )
0137                     break;
0138                 Q_FALLTHROUGH();
0139             case Collections::QueryMaker::TrackArtists:
0140                 if( track->artist()->name() == name )
0141                     matchingTracks.append( track );
0142         }
0143 
0144     if( isLast() || matchingTracks.isEmpty() )
0145         return matchingTracks;
0146     else
0147         return next()->match( matchingTracks );
0148 }
0149 
0150 
0151 
0152 AlbumMatcher::AlbumMatcher( const AlbumPtr &album )
0153     : MemoryMatcher()
0154     , m_album( album )
0155 {}
0156 
0157 TrackList AlbumMatcher::match( Collections::MemoryCollection *memColl )
0158 {
0159     if( !m_album || !memColl )
0160         return TrackList();
0161     AlbumMap albumMap = memColl->albumMap();
0162     if ( albumMap.contains( m_album ) ) // compares albums by value
0163     {
0164         AlbumPtr album = albumMap.value( m_album ); // compares albums by value, too
0165         TrackList matchingTracks = album->tracks();
0166         if ( isLast() )
0167             return matchingTracks;
0168         else
0169             return next()->match( matchingTracks );
0170     }
0171     else
0172         return TrackList();
0173 }
0174 
0175 TrackList AlbumMatcher::match( const TrackList &tracks )
0176 {
0177     if( !m_album )
0178         return TrackList();
0179     TrackList matchingTracks;
0180     QString name = m_album->name();
0181     foreach( TrackPtr track, tracks )
0182         if ( track->album()->name() == name )
0183             matchingTracks.append( track );
0184     if ( isLast() || matchingTracks.isEmpty())
0185         return matchingTracks;
0186     else
0187         return next()->match( matchingTracks );
0188 }
0189 
0190 
0191 
0192 GenreMatcher::GenreMatcher( const GenrePtr &genre )
0193     : MemoryMatcher()
0194     , m_genre( genre )
0195 {}
0196 
0197 TrackList GenreMatcher::match( Collections::MemoryCollection *memColl )
0198 {
0199     if( !m_genre || !memColl )
0200         return TrackList();
0201     GenreMap genreMap = memColl->genreMap();
0202     if ( genreMap.contains( m_genre->name() ) )
0203     {
0204         GenrePtr genre = genreMap.value( m_genre->name() );
0205         TrackList matchingTracks = genre->tracks();
0206         if ( isLast() )
0207             return matchingTracks;
0208         else
0209             return next()->match( matchingTracks );
0210     }
0211     else
0212         return TrackList();
0213 }
0214 
0215 TrackList GenreMatcher::match( const TrackList &tracks )
0216 {
0217     if( !m_genre )
0218         return TrackList();
0219     TrackList matchingTracks;
0220     QString name = m_genre->name();
0221     foreach( TrackPtr track, tracks )
0222         if ( track->genre()->name() == name )
0223             matchingTracks.append( track );
0224     if ( isLast() || matchingTracks.isEmpty())
0225         return matchingTracks;
0226     else
0227         return next()->match( matchingTracks );
0228 }
0229 
0230 
0231 
0232 ComposerMatcher::ComposerMatcher( const ComposerPtr &composer )
0233     : MemoryMatcher()
0234     , m_composer( composer )
0235 {}
0236 
0237 TrackList ComposerMatcher::match( Collections::MemoryCollection *memColl )
0238 {
0239     if( !m_composer || !memColl )
0240         return TrackList();
0241     ComposerMap composerMap = memColl->composerMap();
0242     if ( composerMap.contains( m_composer->name() ) )
0243     {
0244         ComposerPtr composer = composerMap.value( m_composer->name() );
0245         TrackList matchingTracks = composer->tracks();
0246         if ( isLast() )
0247             return matchingTracks;
0248         else
0249             return next()->match( matchingTracks );
0250     }
0251     else
0252         return TrackList();
0253 }
0254 
0255 TrackList ComposerMatcher::match( const TrackList &tracks )
0256 {
0257     if( !m_composer )
0258         return TrackList();
0259     TrackList matchingTracks;
0260     QString name = m_composer->name();
0261     foreach( TrackPtr track, tracks )
0262         if ( track->composer()->name() == name )
0263             matchingTracks.append( track );
0264     if ( isLast() || matchingTracks.isEmpty())
0265         return matchingTracks;
0266     else
0267         return next()->match( matchingTracks );
0268 }
0269 
0270 
0271 
0272 YearMatcher::YearMatcher( const YearPtr &year )
0273     : MemoryMatcher()
0274     , m_year( year )
0275 {}
0276 
0277 TrackList YearMatcher::match( Collections::MemoryCollection *memColl )
0278 {
0279     if( !m_year || !memColl )
0280         return TrackList();
0281     YearMap yearMap = memColl->yearMap();
0282     if ( yearMap.contains( m_year->year() ) )
0283     {
0284         YearPtr year = yearMap.value( m_year->year() );
0285         TrackList matchingTracks = year->tracks();
0286         if ( isLast() )
0287             return matchingTracks;
0288         else
0289             return next()->match( matchingTracks );
0290     }
0291     else
0292         return TrackList();
0293 }
0294 
0295 TrackList YearMatcher::match( const TrackList &tracks )
0296 {
0297     if( !m_year )
0298         return TrackList();
0299     TrackList matchingTracks;
0300     int year = m_year->year();
0301     foreach( TrackPtr track, tracks )
0302         if ( track->year()->year() == year )
0303             matchingTracks.append( track );
0304     if ( isLast() || matchingTracks.isEmpty())
0305         return matchingTracks;
0306     else
0307         return next()->match( matchingTracks );
0308 }
0309 
0310 LabelMatcher::LabelMatcher( const Meta::LabelPtr &label )
0311     : MemoryMatcher()
0312     , m_label( label )
0313 {
0314     //nothing to do
0315 }
0316 
0317 Meta::TrackList
0318 LabelMatcher::match( const Meta::TrackList &tracks )
0319 {
0320     if( !m_label )
0321         return Meta::TrackList();
0322 
0323     Meta::TrackList matchingTracks;
0324     QString name = m_label->name();
0325     //not really efficient...
0326     foreach( const Meta::TrackPtr &track, tracks )
0327     {
0328         foreach( const Meta::LabelPtr &label, track->labels() )
0329         {
0330             if( name == label->name() )
0331             {
0332                 matchingTracks << track;
0333                 break;
0334             }
0335         }
0336     }
0337     if( isLast() || matchingTracks.isEmpty() )
0338         return matchingTracks;
0339     else
0340         return next()->match( matchingTracks );
0341 }
0342 
0343 Meta::TrackList
0344 LabelMatcher::match( Collections::MemoryCollection *memColl )
0345 {
0346     if( !m_label )
0347         return Meta::TrackList();
0348 
0349     Meta::TrackList matchingTracks;
0350 
0351     if( memColl->labelMap().contains( m_label->name() ) )
0352     {
0353         //m_label might actually be a proxy label
0354         Meta::LabelPtr realLabel = memColl->labelMap().value( m_label->name() );
0355         matchingTracks = memColl->labelToTrackMap().value( realLabel );
0356     }
0357     if( isLast() || matchingTracks.isEmpty() )
0358         return matchingTracks;
0359     else
0360         return next()->match( matchingTracks );
0361 }
0362 
0363 
0364 
0365 
0366