/*
* 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.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.Vector;
import org.jajuk.events.JajukEvent;
import org.jajuk.events.JajukEvents;
import org.jajuk.events.ObservationManager;
import org.jajuk.util.Const;
import org.jajuk.util.ReadOnlyIterator;
import org.jajuk.util.UtilFeatures;
import org.jajuk.util.error.JajukException;
/**
* Convenient class to manage genres.
*/
public final class GenreManager extends ItemManager {
/** Self instance. */
private static GenreManager singleton = new GenreManager();
/* List of all known genres */
private Vector<String> genresList; // 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.
*/
private GenreManager() {
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));
// Add preset genres
registerPresetGenres();
}
/**
* Gets the instance.
*
* @return singleton
*/
public static GenreManager getInstance() {
return singleton;
}
/**
* Register a genre.
*
* @param sName
*
* @return the genre
*/
public Genre registerGenre(String sName) {
String sId = createID(sName);
return registerGenre(sId, sName);
}
/**
* Register a genre with a known id.
*
* @param sId
* @param sName
* @return the genre
*/
Genre registerGenre(String sId, String sName) {
Genre genre = getGenreByID(sId);
if (genre != null) {
return genre;
}
genre = new Genre(sId, sName);
registerItem(genre);
// add it in genres list if new
if (!genresList.contains(sName)) {
genresList.add(genre.getName2());
// only sort as soon as we have the Collection fully loaded
if (orderedState) {
sortGenreList();
}
}
return genre;
}
/**
*
*/
private void sortGenreList() {
// Sort items ignoring case
Collections.sort(genresList, 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;
sortGenreList();
super.switchToOrderState();
}
/**
* Register preset genres.
*
*/
private void registerPresetGenres() {
// create default genre list
genresList = new Vector<String>(Arrays.asList(UtilFeatures.GENRES));
Collections.sort(genresList);
for (String genre : genresList) {
registerGenre(genre.intern());
}
}
/**
* Return genre by name.
*
* @param name
*
* @return the genre by name
*/
public Genre getGenreByName(String name) {
Genre out = null;
for (Genre genre : getGenres()) {
if (genre.getName().equals(name)) {
out = genre;
break;
}
}
return out;
}
/**
* Change the item name.
*
* @param old
* @param sNewName
*
* @return new item
*
* @throws JajukException the jajuk exception
*/
Genre changeGenreName(Genre old, String sNewName) throws JajukException {
// check there is actually a change
if (old.getName2().equals(sNewName)) {
return old;
}
Genre newItem = registerGenre(sNewName);
// re apply old properties from old item
newItem.cloneProperties(old);
// update tracks
List<Track> alTracks = TrackManager.getInstance().getTracks();
// we need to create a new list to avoid concurrent exceptions
Iterator<Track> it = alTracks.iterator();
while (it.hasNext()) {
Track track = it.next();
if (track.getGenre().equals(old)) {
TrackManager.getInstance().changeTrackGenre(track, sNewName, null);
}
}
// notify everybody for the file change
Properties properties = new Properties();
properties.put(Const.DETAIL_OLD, old);
properties.put(Const.DETAIL_NEW, newItem);
// Notify interested items (like ambience manager)
ObservationManager.notifySync(new JajukEvent(JajukEvents.GENRE_NAME_CHANGED, properties));
return newItem;
}
/**
* Format the Genre name to be normalized :
* <p>
* -no underscores or other non-ascii characters
* <p>
* -no spaces at the begin and the end
* <p>
* -All in upper case
* <p>
* example: "ROCK".
*
* @param sName
*
* @return the string
*/
public static String format(String sName) {
String sOut;
sOut = sName.trim(); // supress spaces at the begin and the end
sOut = sOut.replace('-', ' '); // move - to space
sOut = sOut.replace('_', ' '); // move _ to space
sOut = sOut.toUpperCase(Locale.getDefault());
return sOut;
}
/*
* (non-Javadoc)
*
* @see org.jajuk.base.ItemManager#getIdentifier()
*/
@Override
public String getXMLTag() {
return Const.XML_GENRES;
}
/**
* Gets the genres list.
*
* @return Human readable list of registrated genres <br>
* ordered (alphabeticaly)
*/
public Vector<String> getGenresList() {
return genresList;
}
/**
* Gets the genre by id.
*
* @param sID Item ID
*
* @return item
*/
public Genre getGenreByID(String sID) {
return (Genre) getItemByID(sID);
}
/**
* Gets the genres.
*
* @return ordered genres list
*/
@SuppressWarnings("unchecked")
public List<Genre> getGenres() {
return (List<Genre>) getItems();
}
/**
* Gets the genres iterator.
*
* @return genres iterator
*/
@SuppressWarnings("unchecked")
public ReadOnlyIterator<Genre> getGenresIterator() {
return new ReadOnlyIterator<Genre>((Iterator<Genre>) getItemsIterator());
}
}