generated from Java-2025Fall/final-vibevault-template
199 lines
6.9 KiB
Java
199 lines
6.9 KiB
Java
package com.vibevault.service;
|
|
|
|
import com.vibevault.dto.PlaylistDTO;
|
|
import com.vibevault.dto.SongCreateDTO;
|
|
import com.vibevault.dto.SongDTO;
|
|
import com.vibevault.exception.ResourceNotFoundException;
|
|
import com.vibevault.exception.UnauthorizedException;
|
|
import com.vibevault.model.Playlist;
|
|
import com.vibevault.model.Song;
|
|
import com.vibevault.model.User;
|
|
import com.vibevault.repository.PlaylistRepository;
|
|
import com.vibevault.repository.UserRepository;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import java.util.List;
|
|
|
|
/**
|
|
* 歌单服务实现
|
|
*
|
|
* 需要实现:
|
|
* - 所有 PlaylistService 接口中定义的方法
|
|
* - 将实体转换为 DTO 返回给调用者
|
|
* - 资源不存在时抛出 ResourceNotFoundException
|
|
* - [Challenge] 检查用户是否有权限操作歌单(所有权检查)
|
|
*/
|
|
@Service
|
|
public class PlaylistServiceImpl implements PlaylistService {
|
|
|
|
private final PlaylistRepository playlistRepository;
|
|
private final UserRepository userRepository;
|
|
|
|
public PlaylistServiceImpl(PlaylistRepository playlistRepository, UserRepository userRepository) {
|
|
this.playlistRepository = playlistRepository;
|
|
this.userRepository = userRepository;
|
|
}
|
|
|
|
@Override
|
|
public List<PlaylistDTO> getAllPlaylists() {
|
|
return playlistRepository.findAll()
|
|
.stream()
|
|
.map(this::toDTO)
|
|
.toList();
|
|
}
|
|
|
|
@Override
|
|
public PlaylistDTO getPlaylistById(Long id) {
|
|
Playlist playlist = playlistRepository.findById(id)
|
|
.orElseThrow(() -> new ResourceNotFoundException("Playlist not found with id: " + id));
|
|
return toDTO(playlist);
|
|
}
|
|
|
|
@Override
|
|
@Transactional
|
|
public PlaylistDTO createPlaylist(String name, String ownerUsername) {
|
|
User owner = userRepository.findByUsername(ownerUsername)
|
|
.orElseThrow(() -> new ResourceNotFoundException("User not found: " + ownerUsername));
|
|
|
|
Playlist playlist = new Playlist(name, owner);
|
|
Playlist savedPlaylist = playlistRepository.save(playlist);
|
|
|
|
return toDTO(savedPlaylist);
|
|
}
|
|
|
|
@Override
|
|
@Transactional
|
|
public PlaylistDTO addSongToPlaylist(Long playlistId, SongCreateDTO song, String username) {
|
|
Playlist playlist = playlistRepository.findById(playlistId)
|
|
.orElseThrow(() -> new ResourceNotFoundException("Playlist not found with id: " + playlistId));
|
|
|
|
// [Challenge] 检查用户是否有权限操作此歌单
|
|
checkPermission(playlist, username);
|
|
|
|
Song newSong = new Song(song.title(), song.artist(), song.durationInSeconds());
|
|
playlist.addSong(newSong);
|
|
|
|
Playlist updatedPlaylist = playlistRepository.save(playlist);
|
|
return toDTO(updatedPlaylist);
|
|
}
|
|
|
|
@Override
|
|
@Transactional
|
|
public void removeSongFromPlaylist(Long playlistId, Long songId, String username) {
|
|
Playlist playlist = playlistRepository.findById(playlistId)
|
|
.orElseThrow(() -> new ResourceNotFoundException("Playlist not found with id: " + playlistId));
|
|
|
|
// [Challenge] 检查用户是否有权限操作此歌单
|
|
checkPermission(playlist, username);
|
|
|
|
Song song = playlist.getSongs().stream()
|
|
.filter(s -> s.getId().equals(songId))
|
|
.findFirst()
|
|
.orElseThrow(() -> new ResourceNotFoundException("Song not found with id: " + songId));
|
|
|
|
playlist.removeSong(song);
|
|
playlistRepository.save(playlist);
|
|
}
|
|
|
|
@Override
|
|
@Transactional
|
|
public void deletePlaylist(Long playlistId, String username) {
|
|
Playlist playlist = playlistRepository.findById(playlistId)
|
|
.orElseThrow(() -> new ResourceNotFoundException("Playlist not found with id: " + playlistId));
|
|
|
|
// [Challenge] 检查用户是否有权限操作此歌单
|
|
checkPermission(playlist, username);
|
|
|
|
playlistRepository.delete(playlist);
|
|
}
|
|
|
|
// ========== Advanced 方法 ==========
|
|
|
|
|
|
|
|
@Override
|
|
@Transactional(readOnly = true)
|
|
public List<PlaylistDTO> searchPlaylists(String keyword) {
|
|
return playlistRepository.findByNameContainingIgnoreCase(keyword)
|
|
.stream()
|
|
.map(this::toDTO)
|
|
.toList();
|
|
}
|
|
|
|
@Override
|
|
@Transactional
|
|
public PlaylistDTO copyPlaylist(Long playlistId, String newName, String username) {
|
|
// 获取要复制的歌单
|
|
Playlist originalPlaylist = playlistRepository.findById(playlistId)
|
|
.orElseThrow(() -> new ResourceNotFoundException("Playlist not found with id: " + playlistId));
|
|
|
|
// 获取当前用户(新歌单的所有者)
|
|
User currentUser = userRepository.findByUsername(username)
|
|
.orElseThrow(() -> new ResourceNotFoundException("User not found: " + username));
|
|
|
|
// 创建新歌单
|
|
Playlist copiedPlaylist = new Playlist(newName, currentUser);
|
|
|
|
// 复制原歌单中的所有歌曲
|
|
originalPlaylist.getSongs().forEach(originalSong -> {
|
|
Song copiedSong = new Song(
|
|
originalSong.getTitle(),
|
|
originalSong.getArtist(),
|
|
originalSong.getDurationInSeconds()
|
|
);
|
|
copiedPlaylist.addSong(copiedSong);
|
|
});
|
|
|
|
// 保存新歌单
|
|
Playlist savedPlaylist = playlistRepository.save(copiedPlaylist);
|
|
|
|
return toDTO(savedPlaylist);
|
|
}
|
|
|
|
// ========== 辅助方法 ==========
|
|
|
|
/**
|
|
* 将 Playlist 实体转换为 DTO
|
|
*/
|
|
private PlaylistDTO toDTO(Playlist playlist) {
|
|
List<SongDTO> songDTOs = playlist.getSongs()
|
|
.stream()
|
|
.map(this::toSongDTO)
|
|
.toList();
|
|
|
|
return new PlaylistDTO(
|
|
playlist.getId(),
|
|
playlist.getName(),
|
|
playlist.getOwner().getUsername(),
|
|
songDTOs
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 将 Song 实体转换为 DTO
|
|
*/
|
|
private SongDTO toSongDTO(Song song) {
|
|
return new SongDTO(
|
|
song.getId(),
|
|
song.getTitle(),
|
|
song.getArtist(),
|
|
song.getDurationInSeconds()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* [Challenge] 检查用户是否有权限操作指定歌单
|
|
* 规则:歌单所有者或管理员可以操作
|
|
*/
|
|
private void checkPermission(Playlist playlist, String username) {
|
|
User currentUser = userRepository.findByUsername(username)
|
|
.orElseThrow(() -> new ResourceNotFoundException("User not found: " + username));
|
|
|
|
// 检查是否是歌单所有者或管理员
|
|
if (!playlist.getOwner().getUsername().equals(username) && !currentUser.getRole().equals("ROLE_ADMIN")) {
|
|
throw new UnauthorizedException("You don't have permission to modify this playlist");
|
|
}
|
|
}
|
|
}
|