net.sourceforge.subsonic.controller.HomeController.java Source code

Java tutorial

Introduction

Here is the source code for net.sourceforge.subsonic.controller.HomeController.java

Source

/*
 This file is part of Subsonic.
    
 Subsonic 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 3 of the License, or
 (at your option) any later version.
    
 Subsonic 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 Subsonic.  If not, see <http://www.gnu.org/licenses/>.
    
 Copyright 2009 (C) Sindre Mehus
 */
package net.sourceforge.subsonic.controller;

import static java.net.URLEncoder.encode;
import static net.sourceforge.subsonic.util.StringUtil.ENCODING_UTF8;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.math.NumberUtils.toInt;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sourceforge.subsonic.Logger;
import net.sourceforge.subsonic.domain.Album;
import net.sourceforge.subsonic.domain.ArtistLink;
import net.sourceforge.subsonic.domain.MediaFile;
import net.sourceforge.subsonic.domain.Player;
import net.sourceforge.subsonic.domain.User;
import net.sourceforge.subsonic.domain.UserSettings;
import net.sourceforge.subsonic.service.MediaFileService;
import net.sourceforge.subsonic.service.PlayerService;
import net.sourceforge.subsonic.service.RatingService;
import net.sourceforge.subsonic.service.SecurityService;
import net.sourceforge.subsonic.service.SettingsService;
import net.sourceforge.subsonic.util.Util;

import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ParameterizableViewController;
import org.springframework.web.servlet.view.RedirectView;

import com.github.hakko.musiccabinet.configuration.Uri;
import com.github.hakko.musiccabinet.domain.model.aggr.ArtistRecommendation;
import com.github.hakko.musiccabinet.domain.model.library.LastFmUser;
import com.github.hakko.musiccabinet.domain.model.library.Period;
import com.github.hakko.musiccabinet.service.ArtistRecommendationService;
import com.github.hakko.musiccabinet.service.LibraryBrowserService;
import com.github.hakko.musiccabinet.service.LibraryUpdateService;
import com.github.hakko.musiccabinet.service.StarService;
import com.github.hakko.musiccabinet.service.lastfm.UserTopArtistsService;

/**
 * Controller for the home page.
 */
public class HomeController extends ParameterizableViewController {

    private static final Logger LOG = Logger.getLogger(HomeController.class);

    private SettingsService settingsService;
    private PlayerService playerService;
    private SecurityService securityService;
    private UserTopArtistsService userTopArtistsService;
    private ArtistRecommendationService artistRecommendationService;
    private LibraryUpdateService libraryUpdateService;
    private LibraryBrowserService libraryBrowserService;
    private MediaFileService mediaFileService;
    private StarService starService;
    private RatingService ratingService;

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        Map<String, Object> map = new HashMap<String, Object>();

        Player player = playerService.getPlayer(request, response);

        User user = securityService.getCurrentUser(request);
        UserSettings userSettings = settingsService.getUserSettings(user.getUsername());
        if (user.isAdminRole() && settingsService.isGettingStartedEnabled()) {
            return new ModelAndView(new RedirectView("gettingStarted.view"));
        }

        if (!libraryBrowserService.hasArtists()) {
            return new ModelAndView(new RedirectView("settings.view"));
        }

        String listType = request.getParameter("listType");
        String listGroup = request.getParameter("listGroup");
        String listUsers = StringUtils.defaultIfEmpty(request.getParameter("listUsers"),
                userSettings.isViewStatsForAllUsers() ? "all" : "current");
        String query = StringUtils.trimToNull(request.getParameter("query"));
        int page = "random".equals(listType) ? 0 : toInt(request.getParameter("page"), 0);
        String lastFmUsername = "current".equals(listUsers) || "topartists".equals(listType)
                || "recommended".equals(listType) ? userSettings.getLastFmUsername() : null;

        if (listType == null) {
            String defaultHomeView = userSettings.getDefaultHomeView();
            if (defaultHomeView != null) {
                int index;
                if ((index = defaultHomeView.indexOf('+')) != -1) {
                    listType = defaultHomeView.substring(0, index);
                    listGroup = defaultHomeView.substring(index + 1);
                } else {
                    listType = defaultHomeView;
                }
            } else {
                listType = "newest";
            }
        }
        if (listGroup == null) {
            listGroup = "topartists".equals(listType) ? "3month" : "Albums";
        }

        if ("topartists".equals(listType) || "recommended".equals(listType) || "Artists".equals(listGroup)) {
            setArtists(listType, listGroup, query, page, userSettings, lastFmUsername, map);
        } else if ("newest".equals(listType) || "Albums".equals(listGroup)) {
            setAlbums(player, listType, query, page, userSettings, lastFmUsername, map);
        } else if ("Songs".equals(listGroup)) {
            setSongs(listType, query, page, userSettings, lastFmUsername, map);
        }

        map.put("player", player);
        map.put("welcomeTitle", settingsService.getWelcomeTitle());
        map.put("welcomeSubtitle", settingsService.getWelcomeSubtitle());
        map.put("welcomeMessage", settingsService.getWelcomeMessage());
        map.put("isIndexCreated", libraryUpdateService.isIndexCreated());
        map.put("listType", listType);
        map.put("listGroup", listGroup);
        map.put("listUsers", listUsers);
        map.put("user", user);
        map.put("lastFmUser", userSettings.getLastFmUsername());

        ModelAndView result = super.handleRequestInternal(request, response);
        result.addObject("model", map);

        return result;
    }

    private void setArtists(String listType, String listGroup, String query, int page, UserSettings userSettings,
            String lastFmUsername, Map<String, Object> map) {
        if ("topartists".equals(listType)) {
            Period period = Period.THREE_MONTHS;
            for (Period p : Period.values()) {
                if (p.getDescription().equals(listGroup)) {
                    period = p;
                }
            }
            if (!isEmpty(lastFmUsername)) {
                List<ArtistRecommendation> topArtists = Util.square(
                        userTopArtistsService.getUserTopArtists(new LastFmUser(lastFmUsername), period, 0, 25));
                map.put("artists", topArtists);
            }
        } else {
            final int ARTISTS = userSettings.getDefaultHomeArtists();
            int offset = page * ARTISTS, limit = ARTISTS + 1;

            List<ArtistRecommendation> artists = Util
                    .square(getArtists(listType, lastFmUsername, offset, limit, query, userSettings));

            if (artists.size() > ARTISTS) {
                map.put("morePages", true);
                artists.remove(ARTISTS);
            }
            map.put("page", page);
            map.put("artists", artists);

            if ("recommended".equals(listType)) {
                map.put("artistsNotInLibrary", getRecommendedArtistsNotInLibrary(lastFmUsername, userSettings));
            }
        }
        map.put("artistGridWidth", userSettings.getArtistGridWidth());
    }

    private List<ArtistLink> getRecommendedArtistsNotInLibrary(String lastFmUsername, UserSettings userSettings) {
        List<ArtistLink> artistsNotInLibrary = new ArrayList<>();
        short amount = userSettings.getRecommendedArtists();
        boolean onlyAlbumArtists = userSettings.isOnlyAlbumArtistRecommendations();
        List<String> namesNotInLibrary = artistRecommendationService
                .getRecommendedArtistsNotInLibrary(lastFmUsername, amount, onlyAlbumArtists);
        for (String name : namesNotInLibrary) {
            artistsNotInLibrary.add(new ArtistLink(name, getURLEncodedName(name)));
        }
        return artistsNotInLibrary;
    }

    private String getURLEncodedName(String name) {
        try {
            return encode(name, ENCODING_UTF8);
        } catch (UnsupportedEncodingException e) {
            return name;
        }
    }

    private List<ArtistRecommendation> getArtists(String listType, String lastFmUsername, int offset, int limit,
            String query, UserSettings userSettings) {
        boolean onlyAlbumArtists = userSettings.isOnlyAlbumArtistRecommendations();
        switch (listType) {
        case "recent":
            return libraryBrowserService.getRecentlyPlayedArtists(lastFmUsername, onlyAlbumArtists, offset, limit,
                    query);
        case "frequent":
            return libraryBrowserService.getMostPlayedArtists(lastFmUsername, offset, limit, query);
        case "starred":
            return libraryBrowserService.getStarredArtists(lastFmUsername, offset, limit, query);
        case "random":
            return libraryBrowserService.getRandomArtists(onlyAlbumArtists, limit);
        case "recommended":
            return artistRecommendationService.getRecommendedArtistsInLibrary(lastFmUsername, offset, limit,
                    userSettings.isOnlyAlbumArtistRecommendations());
        }
        return null;
    }

    private void setAlbums(Player player, String listType, String query, int page, UserSettings userSettings,
            String lastFmUsername, Map<String, Object> map) {
        final int ALBUMS = userSettings.getDefaultHomeAlbums();
        int offset = page * ALBUMS, limit = ALBUMS + 1;

        List<Album> albums = mediaFileService.getAlbums(
                getAlbums(listType, query, offset, limit, lastFmUsername, null, -1, -1, player.isSpotifyEnabled()));

        if (albums.size() > ALBUMS) {
            map.put("morePages", true);
            albums.remove(ALBUMS);
        }
        map.put("page", page);
        map.put("albums", albums);
        map.put("isAlbumStarred", starService.getStarredAlbumsMask(lastFmUsername, getAlbumUris(albums)));
        map.put("artistGridWidth", userSettings.getArtistGridWidth());
        map.put("albumGridLayout", userSettings.isAlbumGridLayout());
    }

    private List<? extends Uri> getAlbumUris(List<Album> albums) {
        List<Uri> albumIds = new ArrayList<>();
        for (Album album : albums) {
            albumIds.add(album.getUri());
        }
        return albumIds;
    }

    public List<com.github.hakko.musiccabinet.domain.model.music.Album> getAlbums(String listType, String query,
            int offset, int limit, String lastFmUsername, String genre, int fromYear, int toYear,
            boolean spotifyEnabled) {

        switch (listType) {
        case "highest":
            return ratingService.getHighestRatedAlbums(offset, limit);
        case "frequent":
            return libraryBrowserService.getMostPlayedAlbums(spotifyEnabled, lastFmUsername, offset, limit, query);
        case "recent":
            return libraryBrowserService.getRecentlyPlayedAlbums(spotifyEnabled, lastFmUsername, offset, limit,
                    query);
        case "newest":
            return libraryBrowserService.getRecentlyAddedAlbums(spotifyEnabled, offset, limit, query);
        case "starred":
            return libraryBrowserService.getStarredAlbums(spotifyEnabled, lastFmUsername, offset, limit, query);
        case "alphabeticalbyartist":
            return libraryBrowserService.getAlbumsByArtist(spotifyEnabled, lastFmUsername, offset, limit, query);
        case "alphabeticalbyname":
            return libraryBrowserService.getAlbumsByName(spotifyEnabled, lastFmUsername, offset, limit, query);
        case "bygenre":
            return libraryBrowserService.getAlbumsByGenre(spotifyEnabled, lastFmUsername, offset, limit, query,
                    genre);
        case "byyear":
            return libraryBrowserService.getAlbumsByYear(spotifyEnabled, lastFmUsername, offset, limit, query,
                    fromYear, toYear);
        case "random":
            return libraryBrowserService.getRandomAlbums(spotifyEnabled, limit);
        }
        return null;
    }

    private void setSongs(String listType, String query, int page, UserSettings userSettings, String lastFmUsername,
            Map<String, Object> map) {
        final int SONGS = userSettings.getDefaultHomeSongs();
        int offset = page * SONGS, limit = SONGS + 1;

        List<? extends Uri> mediaFileIds = getMediaFileUris(listType, query, offset, limit, lastFmUsername);
        mediaFileService.loadMediaFiles(mediaFileIds);
        List<MediaFile> mediaFiles = mediaFileService.getMediaFiles(mediaFileIds);

        if (mediaFiles.size() > SONGS) {
            map.put("morePages", true);
            mediaFileIds.remove(SONGS);
            mediaFiles.remove(SONGS);
        }
        map.put("page", page);
        map.put("trackIds", mediaFileIds);
        map.put("mediaFiles", mediaFiles);
        map.put("multipleArtists", true);
        map.put("visibility", userSettings.getHomeVisibility());
        map.put("isTrackStarred", starService.getStarredTracksMask(lastFmUsername, getTrackUris(mediaFiles)));
    }

    private List<Uri> getTrackUris(List<MediaFile> mediaFiles) {
        List<Uri> trackUris = new ArrayList<>();
        for (MediaFile mediaFile : mediaFiles) {
            trackUris.add(mediaFile.getUri());
        }
        return trackUris;
    }

    private List<? extends Uri> getMediaFileUris(String listType, String query, int offset, int limit,
            String lastFmUsername) {
        switch (listType) {
        case "recent":
            return libraryBrowserService.getRecentlyPlayedTrackUris(lastFmUsername, offset, limit, query);
        case "frequent":
            return libraryBrowserService.getMostPlayedTrackUris(lastFmUsername, offset, limit, query);
        case "starred":
            return libraryBrowserService.getStarredTrackUris(lastFmUsername, offset, limit, query);
        case "random":
            return libraryBrowserService.getRandomTrackUris(limit);
        }
        return null;
    }

    public void setSettingsService(SettingsService settingsService) {
        this.settingsService = settingsService;
    }

    public void setSecurityService(SecurityService securityService) {
        this.securityService = securityService;
    }

    public void setPlayerService(PlayerService playerService) {
        this.playerService = playerService;
    }

    public void setUserTopArtistsService(UserTopArtistsService userTopArtistsService) {
        this.userTopArtistsService = userTopArtistsService;
    }

    public void setArtistRecommendationService(ArtistRecommendationService artistRecommendationService) {
        this.artistRecommendationService = artistRecommendationService;
    }

    public void setLibraryUpdateService(LibraryUpdateService libraryUpdateService) {
        this.libraryUpdateService = libraryUpdateService;
    }

    public void setLibraryBrowserService(LibraryBrowserService libraryBrowserService) {
        this.libraryBrowserService = libraryBrowserService;
    }

    public void setMediaFileService(MediaFileService mediaFileService) {
        this.mediaFileService = mediaFileService;
    }

    public void setStarService(StarService starService) {
        this.starService = starService;
    }

    public void setRatingService(RatingService ratingService) {
        this.ratingService = ratingService;
    }

}