package me.moodcat.database.controllers;
import static me.moodcat.database.entities.QSong.song;
import java.util.List;
import javax.persistence.EntityManager;
import me.moodcat.database.embeddables.VAVector;
import me.moodcat.database.entities.Room;
import me.moodcat.database.entities.Song;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import com.mysema.query.types.expr.NumberExpression;
/**
* Used to retrieve songs from the database.
*/
public class SongDAO extends AbstractDAO<Song> {
private static final int AMOUNT_OF_SONGS = 25;
private static final double VECTOR_DISTANCE_DELTA = 0.1;
@Inject
public SongDAO(final EntityManager entityManager) {
super(entityManager);
}
/**
* Get all the lists stored in the database.
*
* @return The list of songs stored in the database.
*/
@Transactional
public List<Song> listSongs() {
return this.query().from(song)
.list(song);
}
/**
* Retrieve random unclassified songs from the database.
*
* @param limit
* The number of songs to retrieve.
* @return A list of random songs.
*/
@Transactional
public List<Song> listRandomsongs(final int limit) {
return query()
.from(song)
.where(song.valenceArousal.location.distance(VAVector.ZERO.getLocation()).lt(
VECTOR_DISTANCE_DELTA))
.orderBy(NumberExpression.random().asc())
.limit(limit)
.list(song);
}
/**
* Get a song by name.
*
* @param name
* The (case-ignored) name of the song.
* @return The song, if found.
*/
@Transactional
public Song findByName(final String name) {
return ensureExists(this.query().from(song)
.where(song.name.equalsIgnoreCase(name))
.singleResult(song));
}
/**
* Get a song by id.
*
* @param id
* The id of song.
* @return The song, if found.
*/
@Transactional
public Song findById(final int id) {
return ensureExists(this.query().from(song)
.where(song.id.eq(id))
.singleResult(song));
}
/**
* Get a song by SoundCloud id.
*
* @param id
* The SoundCloud id of the song.
* @return The song, if found.
*/
@Transactional
public Song findBySoundCloudId(final int id) {
return ensureExists(this.query().from(song)
.where(song.soundCloudId.eq(id))
.singleResult(song));
}
/**
* Find songs for distance.
*
* @param vector
* Vector to search
* @param limit
* limit of results
* @return List of songs
*/
@Transactional
public List<Song> findForDistance(final VAVector vector, final long limit) {
return query().from(song)
.orderBy(song.valenceArousal.location.distance(vector.getLocation()).asc())
.limit(limit)
.list(song);
}
/**
* Find songs for a room.
*
* @param fetchingRoom
* Room to search for.
* @return List of songs
*/
@Transactional
public List<Song> findNewSongsFor(final Room fetchingRoom) {
return query()
.from(song)
.where(song.exclusions.contains(fetchingRoom).not())
.orderBy(
song.valenceArousal.location.distance(
fetchingRoom.getVaVector().getLocation()).asc())
.limit(AMOUNT_OF_SONGS)
.list(song);
}
}