/* * Jajuk * Copyright (C) The Jajuk Team * http://jajuk.info * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package org.jajuk.base; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Vector; import org.jajuk.events.JajukEvent; import org.jajuk.events.JajukEvents; import org.jajuk.events.ObservationManager; import org.jajuk.services.players.QueueModel; import org.jajuk.util.Const; import org.jajuk.util.ReadOnlyIterator; import org.jajuk.util.error.JajukException; /** * Convenient class to manage artists. */ public final class ArtistManager extends ItemManager { /** Self instance. */ private static ArtistManager singleton = new ArtistManager(); /** List of all known artists. */ private Vector<String> artistsList = new Vector<String>(100); // NOPMD /** note if we have already fully loaded the Collection to speed up initial startup */ private volatile boolean orderedState = false; /** * No constructor available, only static access. * Not private to allow AlbumArtistManager extends */ ArtistManager() { super(); // register properties // ID registerProperty(new PropertyMetaInformation(Const.XML_ID, false, true, false, false, false, String.class, null)); // Name registerProperty(new PropertyMetaInformation(Const.XML_NAME, false, true, true, true, false, String.class, null)); // Expand registerProperty(new PropertyMetaInformation(Const.XML_EXPANDED, false, false, false, false, true, Boolean.class, false)); } /** * Gets the instance. * * @return singleton */ public static ArtistManager getInstance() { return singleton; } /** * Register an artist. * * @param sName The name of the artist to search for. * * @return the artist */ public Artist registerArtist(String sName) { String sId = createID(sName); return registerArtist(sId, sName); } /** * Register an artist with a known id. * * @param sId the ID of the new artist. * @param sName The name of the new artist. * @return the artist */ Artist registerArtist(String sId, String sName) { Artist artist = getArtistByID(sId); // if we have this artist already, simply return the existing one if (artist != null) { return artist; } artist = new Artist(sId, sName); registerItem(artist); // add it in genres list if new if (!artistsList.contains(sName)) { artistsList.add(artist.getName2()); // only sort as soon as we have the Collection fully loaded if (orderedState) { sortArtistList(); } } return artist; } private void sortArtistList() { // Sort items ignoring case Collections.sort(artistsList, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareToIgnoreCase(o2); } }); } /* (non-Javadoc) * @see org.jajuk.base.ItemManager#switchToOrderState() */ @Override public void switchToOrderState() { // bring this Manager to ordered state when Collection is fully loaded orderedState = true; sortArtistList(); super.switchToOrderState(); } /** * Change the item name. * * @param old The name of the artist to update. * @param sNewName The new name of the artist. * * @return The new Album-Instance. * * @throws JajukException Thrown if adjusting the name fails for some reason. */ Artist changeArtistName(Artist old, String sNewName) throws JajukException { // check if there is actually a change if (old.getName2().equals(sNewName)) { return old; } // find out if the QueueModel is playing this track before we change the track! boolean queueNeedsUpdate = false; if (QueueModel.getPlayingFile() != null && QueueModel.getPlayingFile().getTrack().getArtist().equals(old)) { queueNeedsUpdate = true; } Artist newItem = registerArtist(sNewName); // re apply old properties from old item newItem.cloneProperties(old); // update tracks for (Track track : TrackManager.getInstance().getTracks()) { if (track.getArtist().equals(old)) { TrackManager.getInstance().changeTrackArtist(track, sNewName, null); } } // if current track artist name is changed, notify it if (queueNeedsUpdate) { ObservationManager.notify(new JajukEvent(JajukEvents.ARTIST_CHANGED)); } return newItem; } /* * (non-Javadoc) * * @see org.jajuk.base.ItemManager#getIdentifier() */ @Override public String getXMLTag() { return Const.XML_ARTISTS; } /** * Gets the artists list. * * @return artists as a string list (used for artists combos) */ public static Vector<String> getArtistsList() { return getInstance().artistsList; } /** * Gets the artist by id. * * @param sID Item ID * * @return Element */ Artist getArtistByID(String sID) { return (Artist) getItemByID(sID); } /** * Gets the artists. * * @return ordered albums list */ @SuppressWarnings("unchecked") public List<Artist> getArtists() { return (List<Artist>) getItems(); } /** * Gets the artists iterator. * * @return artists iterator */ @SuppressWarnings("unchecked") public ReadOnlyIterator<Artist> getArtistsIterator() { return new ReadOnlyIterator<Artist>((Iterator<Artist>) getItemsIterator()); } /** * Get ordered list of artists associated with this item. * * @param item The artist item to look for. * * @return the associated artists */ public List<Artist> getAssociatedArtists(Item item) { lock.readLock().lock(); try { List<Artist> out; if (item instanceof Track) { out = new ArrayList<Artist>(1); out.add(((Track) item).getArtist()); } else { // [Perf] If item is a track, just return its artist // Use a set to avoid dups Set<Artist> artistSet = new HashSet<Artist>(); List<Track> tracks = TrackManager.getInstance().getAssociatedTracks(item, true); for (Track track : tracks) { artistSet.add(track.getArtist()); } out = new ArrayList<Artist>(artistSet); Collections.sort(out); } return out; } finally { lock.readLock().unlock(); } } /** * Gets the artist by name. * * @param name The name of the artist. * * @return associated artist (case insensitive) or null if no match */ public Artist getArtistByName(String name) { lock.readLock().lock(); try { Artist out = null; for (ReadOnlyIterator<Artist> it = getArtistsIterator(); it.hasNext();) { Artist artist = it.next(); if (artist.getName().equals(name)) { out = artist; break; } } return out; } finally { lock.readLock().unlock(); } } }