Changeset 0519e8d
- Timestamp:
- 08/05/26 18:33:37 (9 hours ago)
- Branches:
- main
- Parents:
- e111525
- Location:
- finkwave/src/main/java/com/ukim/finki/develop/finkwave
- Files:
-
- 3 added
- 13 edited
- 2 moved
-
controller/GlobalExceptionHandler.java (modified) (2 diffs)
-
model/Contribution.java (moved) (moved from finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ArtistContribution.java ) (2 diffs)
-
model/ContributionId.java (moved) (moved from finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ArtistContributionId.java ) (2 diffs)
-
model/ContributionRole.java (added)
-
model/ContributionRoleId.java (added)
-
model/MusicalEntity.java (modified) (1 diff)
-
model/MusicalRole.java (added)
-
model/Playlist.java (modified) (2 diffs)
-
model/User.java (modified) (1 diff)
-
repository/AlbumRepository.java (modified) (1 diff)
-
repository/ArtistContributionRepository.java (modified) (2 diffs)
-
repository/LikeRepository.java (modified) (1 diff)
-
repository/PlaylistRepository.java (modified) (1 diff)
-
repository/SongRepository.java (modified) (9 diffs)
-
service/AlbumService.java (modified) (1 diff)
-
service/MusicalEntityService.java (modified) (11 diffs)
-
service/NonAdminUserService.java (modified) (1 diff)
-
service/PlaylistService.java (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/GlobalExceptionHandler.java
re111525 r0519e8d 10 10 import org.springframework.http.ResponseEntity; 11 11 import org.springframework.security.core.userdetails.UsernameNotFoundException; 12 import org.springframework.web.bind.MissingServletRequestParameterException; 12 13 import org.springframework.web.bind.annotation.ExceptionHandler; 13 14 import org.springframework.web.bind.annotation.RestControllerAdvice; … … 96 97 } 97 98 99 @ExceptionHandler(MissingServletRequestParameterException.class) 100 public ResponseEntity<Map<String, String>> handleMissingParam(MissingServletRequestParameterException ex) { 101 return ResponseEntity 102 .status(HttpStatus.BAD_REQUEST) 103 .body(Map.of("error", "Missing required request parameter '" + ex.getParameterName() + "'.")); 104 } 105 98 106 @ExceptionHandler(Exception.class) 99 107 public ResponseEntity<Map<String, String>> handleGenericException(Exception ex) { -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Contribution.java
re111525 r0519e8d 10 10 @Setter 11 11 @Entity 12 @Table(name = " artist_contributions", schema = "project")13 public class ArtistContribution {12 @Table(name = "contributions", schema = "project") 13 public class Contribution { 14 14 @EmbeddedId 15 private ArtistContributionId id; 15 private ContributionId id; 16 17 @MapsId("musicalEntityId") 18 @ManyToOne(fetch = FetchType.LAZY, optional = false) 19 @OnDelete(action = OnDeleteAction.CASCADE) 20 @JoinColumn(name = "musical_entity_id", nullable = false) 21 private MusicalEntity musicalEntity; 16 22 17 23 @MapsId("artistId") … … 21 27 private Artist artist; 22 28 23 @MapsId("musicalEntityId") 24 @ManyToOne(fetch = FetchType.LAZY, optional = false) 25 @OnDelete(action = OnDeleteAction.CASCADE) 26 @JoinColumn(name = "musical_entity_id", nullable = false) 27 private MusicalEntity musicalEntity; 28 29 @Column(name = "role", nullable = false, length = Integer.MAX_VALUE) 30 private String role; 29 @Column(name = "contribution_order", nullable = false) 30 private Integer contributionOrder; 31 31 32 32 } -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ContributionId.java
re111525 r0519e8d 13 13 @Setter 14 14 @Embeddable 15 public class ArtistContributionId implements Serializable { 16 private static final long serialVersionUID = -3193987026608380950L; 15 public class ContributionId implements Serializable { 16 private static final long serialVersionUID = -3193987026608380951L; 17 @Column(name = "musical_entity_id", nullable = false) 18 private Long musicalEntityId; 19 17 20 @Column(name = "artist_id", nullable = false) 18 21 private Long artistId; 19 20 @Column(name = "musical_entity_id", nullable = false)21 private Long musicalEntityId;22 22 23 23 @Override … … 25 25 if (this == o) return true; 26 26 if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; 27 ArtistContributionId entity = (ArtistContributionId) o;28 return Objects.equals(this. artistId, entity.artistId) &&29 Objects.equals(this. musicalEntityId, entity.musicalEntityId);27 ContributionId entity = (ContributionId) o; 28 return Objects.equals(this.musicalEntityId, entity.musicalEntityId) && 29 Objects.equals(this.artistId, entity.artistId); 30 30 } 31 31 32 32 @Override 33 33 public int hashCode() { 34 return Objects.hash( artistId, musicalEntityId);34 return Objects.hash(musicalEntityId, artistId); 35 35 } 36 36 -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/MusicalEntity.java
re111525 r0519e8d 34 34 private LocalDate releaseDate; 35 35 36 private String cover;37 38 36 @ManyToOne(fetch = FetchType.LAZY) 39 37 @OnDelete(action = OnDeleteAction.CASCADE) -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Playlist.java
re111525 r0519e8d 24 24 private Long id; 25 25 26 @Column(name = "cover", length = Integer.MAX_VALUE)27 private String cover;28 29 26 @Column(name = "name", nullable = false, length = Integer.MAX_VALUE) 30 27 private String name; … … 35 32 private Listener createdBy; 36 33 37 public Playlist(String cover, String name, Listener createdBy) { 38 this.cover = cover; 34 public Playlist(String name, Listener createdBy) { 39 35 this.name = name; 40 36 this.createdBy = createdBy; -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/User.java
re111525 r0519e8d 31 31 private String email; 32 32 33 @Column(n ullable = false, length = Integer.MAX_VALUE)33 @Column(name = "password_hash", nullable = false, length = Integer.MAX_VALUE) 34 34 @JsonIgnore 35 35 private String password; -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/AlbumRepository.java
re111525 r0519e8d 18 18 @Query(""" 19 19 SELECT NEW com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto( 20 a.id, me.title, me.genre, 'ALBUM', u.fullName, u.username, me.cover, FALSE )20 a.id, me.title, me.genre, 'ALBUM', u.fullName, u.username, CAST(NULL AS string), FALSE ) 21 21 FROM Album a 22 22 JOIN a.musicalEntities me -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ArtistContributionRepository.java
re111525 r0519e8d 8 8 import org.springframework.stereotype.Repository; 9 9 10 import com.ukim.finki.develop.finkwave.model. ArtistContribution;11 import com.ukim.finki.develop.finkwave.model. ArtistContributionId;10 import com.ukim.finki.develop.finkwave.model.Contribution; 11 import com.ukim.finki.develop.finkwave.model.ContributionId; 12 12 import com.ukim.finki.develop.finkwave.model.dto.ArtistContributionDto; 13 13 import com.ukim.finki.develop.finkwave.model.dto.ArtistContributionSummaryDto; 14 14 15 15 @Repository 16 public interface ArtistContributionRepository extends JpaRepository< ArtistContribution, ArtistContributionId> {16 public interface ArtistContributionRepository extends JpaRepository<Contribution, ContributionId> { 17 17 18 18 @Query(""" 19 19 SELECT NEW com.ukim.finki.develop.finkwave.model.dto.ArtistContributionDto( 20 ac.musicalEntity.id, ac.musicalEntity.title, ac.musicalEntity.genre, ac.role,20 ac.musicalEntity.id, ac.musicalEntity.title, ac.musicalEntity.genre, CAST(ac.contributionOrder AS string), 21 21 (CASE WHEN s.id IS NOT NULL THEN 'SONG' 22 22 WHEN a.id IS NOT NULL THEN 'ALBUM' 23 23 ELSE 'Unknown' END), 24 24 (CASE WHEN l.id IS NOT NULL THEN true ELSE false END), 25 ac.musicalEntity.cover,25 CAST(NULL AS string), 26 26 s.link) 27 FROM ArtistContribution ac27 FROM Contribution ac 28 28 LEFT JOIN Song s ON s.musicalEntities.id=ac.musicalEntity.id 29 29 LEFT JOIN Album a ON a.musicalEntities.id=ac.musicalEntity.id … … 36 36 @Query(""" 37 37 SELECT NEW com.ukim.finki.develop.finkwave.model.dto.ArtistContributionSummaryDto( 38 ac.artist.nonAdminUser.user.fullName, ac.role38 ac.artist.nonAdminUser.user.fullName, CAST(ac.contributionOrder AS string) 39 39 ) 40 FROM ArtistContribution ac40 FROM Contribution ac 41 41 WHERE ac.id.musicalEntityId = :songId 42 42 """) -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/LikeRepository.java
re111525 r0519e8d 24 24 u.fullName, 25 25 u.username, 26 me.cover,26 CAST(NULL AS string), 27 27 (CASE WHEN currentUserLike.id IS NOT NULL THEN true ELSE false END)) 28 28 FROM Like l -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/PlaylistRepository.java
re111525 r0519e8d 28 28 @Query(""" 29 29 SELECT NEW com.ukim.finki.develop.finkwave.model.dto.BasicPlaylistDto( 30 p.id, p.name, p.cover, (SELECT COUNT(*) FROM PlaylistSong ps where ps.playlist.id = p.id)30 p.id, p.name, CAST(NULL AS string), (SELECT COUNT(*) FROM PlaylistSong ps where ps.playlist.id = p.id) 31 31 ) 32 32 FROM Playlist p -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/SongRepository.java
re111525 r0519e8d 17 17 @Query(""" 18 18 SELECT NEW com.ukim.finki.develop.finkwave.model.dto.SongWithLinkDto( 19 s.id, me.title, me.genre, 'SONG', u.fullName, u.username, me.cover,19 s.id, me.title, me.genre, 'SONG', u.fullName, u.username, CAST(NULL AS string), 20 20 (CASE WHEN :currentUserId IS NOT NULL AND l.id IS NOT NULL THEN true ELSE false END), 21 21 s.link … … 34 34 @Query(""" 35 35 SELECT NEW com.ukim.finki.develop.finkwave.model.dto.SongWithLinkDto( 36 s.id, me.title, me.genre, 'SONG', u.fullName, u.username, me.cover,36 s.id, me.title, me.genre, 'SONG', u.fullName, u.username, CAST(NULL AS string), 37 37 (CASE WHEN :currentUserId IS NOT NULL AND l.id IS NOT NULL THEN true ELSE false END), 38 38 s.link … … 57 57 s.musicalEntities.releasedBy.nonAdminUser.user.fullName, 58 58 s.musicalEntities.releasedBy.nonAdminUser.user.username, 59 s.musicalEntities.cover,59 CAST(NULL AS string), 60 60 (EXISTS (SELECT 1 FROM Like l WHERE l.musicalEntity.id = s.id AND l.listener.id = :currentUserId)), 61 61 s.album.musicalEntities.title, … … 71 71 s.musicalEntities.releasedBy.nonAdminUser.user.fullName, 72 72 s.musicalEntities.releasedBy.nonAdminUser.user.username, 73 s.musicalEntities.cover,74 73 s.album.musicalEntities.title, 75 74 s.album.musicalEntities.id … … 87 86 u.fullName, 88 87 u.username, 89 me.cover,88 CAST(NULL AS string), 90 89 (EXISTS ( 91 90 SELECT 1 FROM Like l … … 116 115 t.username, 117 116 t.link, 118 t.cover117 NULL 119 118 FROM ( 120 119 SELECT DISTINCT ON (l.song_id) … … 123 122 u.full_name, 124 123 u.username, 125 me.cover,126 124 s.link, 127 125 l.timestamp … … 146 144 u.fullName, 147 145 u.username, 148 me.cover,146 CAST(NULL AS string), 149 147 (EXISTS ( 150 148 SELECT 1 FROM Like l … … 177 175 ELSE NULL 178 176 END), 179 me.cover,177 CAST(NULL AS string), 180 178 me.releaseDate 181 179 ) -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AlbumService.java
re111525 r0519e8d 36 36 album.getMusicalEntities().getReleasedBy().getNonAdminUser().getUser().getFullName(), 37 37 album.getMusicalEntities().getReleasedBy().getNonAdminUser().getUser().getUsername(), 38 album.getMusicalEntities().getCover(),38 null, 39 39 likeRepository.isLikedByUser(currentUserId)); 40 40 List<SongWithLinkDto>songsFromAlbum=songRepository.findSongsByAlbum(id,currentUserId); -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/MusicalEntityService.java
re111525 r0519e8d 2 2 3 3 import java.io.IOException; 4 import java.nio.file.Files;5 import java.nio.file.Path;6 import java.nio.file.Paths;7 4 import java.time.LocalDate; 8 5 import java.util.HashSet; 9 6 import java.util.List; 10 7 import java.util.Set; 11 import java.util.UUID;12 8 13 9 import org.springframework.stereotype.Service; 14 10 import org.springframework.transaction.annotation.Transactional; 15 import org.springframework.web.multipart.MultipartFile;16 11 17 import com.ukim.finki.develop.finkwave.exceptions.InvalidFileException;18 12 import com.ukim.finki.develop.finkwave.model.Album; 19 13 import com.ukim.finki.develop.finkwave.model.Artist; 20 import com.ukim.finki.develop.finkwave.model. ArtistContribution;21 import com.ukim.finki.develop.finkwave.model. ArtistContributionId;14 import com.ukim.finki.develop.finkwave.model.Contribution; 15 import com.ukim.finki.develop.finkwave.model.ContributionId; 22 16 import com.ukim.finki.develop.finkwave.model.MusicalEntity; 23 17 import com.ukim.finki.develop.finkwave.model.Song; … … 43 37 MusicalEntityRepository musicalEntityRepository; 44 38 45 private static final long MAX_FILE_SIZE = 2_000_000;46 private static final String MAIN_VOCAL_ROLE = "MAIN VOCAL";47 39 // the publishing artist is always recorded first 40 private static final int PUBLISHING_ARTIST_ORDER = 1; 41 48 42 @Transactional 49 43 public void handleSongPublish(PublishSongRequestDto requestDto) throws IOException { … … 54 48 requestDto.getTitle(), 55 49 requestDto.getGenre(), 56 requestDto.getCover(),57 50 artist 58 51 ); … … 65 58 66 59 // add publishing artist 67 saveContribution(artist, musicalEntity, MAIN_VOCAL_ROLE);60 saveContribution(artist, musicalEntity, PUBLISHING_ARTIST_ORDER); 68 61 69 62 // add additional contributors … … 72 65 73 66 @Transactional 74 protected MusicalEntity createMusicalEntity(String title, String genre, MultipartFile cover, Artist releasedBy) 75 throws IOException { 76 MusicalEntity.MusicalEntityBuilder builder = MusicalEntity.builder() 67 protected MusicalEntity createMusicalEntity(String title, String genre, Artist releasedBy) { 68 MusicalEntity musicalEntity = MusicalEntity.builder() 77 69 .title(title) 78 70 .genre(genre) 79 71 .releaseDate(LocalDate.now()) 80 .releasedBy(releasedBy); 72 .releasedBy(releasedBy) 73 .build(); 81 74 82 if (cover != null && !cover.isEmpty()) { 83 try { 84 String filename = saveCoverPhoto(cover); 85 builder.cover("profile-pictures/" + filename); 86 } catch (Exception ignored) {} 87 } 88 89 return musicalEntityRepository.save(builder.build()); 75 return musicalEntityRepository.save(musicalEntity); 90 76 } 91 77 92 78 @Transactional 93 protected void saveContribution(Artist artist, MusicalEntity musicalEntity, String role) {94 ArtistContributionId id = new ArtistContributionId();79 protected void saveContribution(Artist artist, MusicalEntity musicalEntity, int contributionOrder) { 80 ContributionId id = new ContributionId(); 95 81 id.setArtistId(artist.getId()); 96 82 id.setMusicalEntityId(musicalEntity.getId()); 97 83 98 ArtistContribution contribution = new ArtistContribution();84 Contribution contribution = new Contribution(); 99 85 contribution.setId(id); 100 86 contribution.setArtist(artist); 101 87 contribution.setMusicalEntity(musicalEntity); 102 contribution.set Role(role);88 contribution.setContributionOrder(contributionOrder); 103 89 104 90 artistContributionRepository.save(contribution); … … 109 95 if (contributors == null) return; 110 96 97 int order = PUBLISHING_ARTIST_ORDER + 1; 111 98 for (ArtistContributionSummaryDto contributorDto : contributors) { 112 99 if (contributorDto.getId() == null) continue; 113 100 114 101 Artist contributor = artistService.getArtistById(contributorDto.getId()); 115 saveContribution(contributor, musicalEntity, contributorDto.getRole());102 saveContribution(contributor, musicalEntity, order++); 116 103 } 117 104 } … … 126 113 requestDto.getTitle(), 127 114 requestDto.getGenre(), 128 requestDto.getCover(),129 115 artist 130 116 ); … … 135 121 136 122 // add publishing artist 137 saveContribution(artist, albumMusicalEntity, MAIN_VOCAL_ROLE);123 saveContribution(artist, albumMusicalEntity, PUBLISHING_ARTIST_ORDER); 138 124 139 // track artists already added to avoid duplicates 125 // track artists already added to avoid duplicates, and the next order slot at album level 140 126 Set<Long> albumContributorIds = new HashSet<>(); 141 127 albumContributorIds.add(artist.getId()); 128 int[] nextAlbumOrder = { PUBLISHING_ARTIST_ORDER + 1 }; 142 129 143 130 List<AlbumSongsDto> albumSongs = requestDto.getAlbumSongs(); 144 131 for (AlbumSongsDto songDto : albumSongs) { 145 createSongForAlbum(albumMusicalEntity, album, songDto, artist, albumContributorIds );132 createSongForAlbum(albumMusicalEntity, album, songDto, artist, albumContributorIds, nextAlbumOrder); 146 133 } 147 134 } … … 150 137 @Transactional 151 138 protected void createSongForAlbum(MusicalEntity albumMe, Album album, AlbumSongsDto songDto, 152 Artist publishingArtist, Set<Long> albumContributorIds ) {139 Artist publishingArtist, Set<Long> albumContributorIds, int[] nextAlbumOrder) { 153 140 MusicalEntity songMusicalEntity = MusicalEntity.builder() 154 141 .title(songDto.getTitle()) 155 142 .releaseDate(albumMe.getReleaseDate()) 156 143 .releasedBy(albumMe.getReleasedBy()) 157 .cover(albumMe.getCover())158 144 .genre(albumMe.getGenre()) 159 145 .build(); … … 166 152 songRepository.save(song); 167 153 168 // add publishing artist as MAIN VOCALto this song169 saveContribution(publishingArtist, songMusicalEntity, MAIN_VOCAL_ROLE);154 // add publishing artist as first contributor to this song 155 saveContribution(publishingArtist, songMusicalEntity, PUBLISHING_ARTIST_ORDER); 170 156 171 157 // add song-specific contributors 172 158 List<ArtistContributionSummaryDto> songContributors = songDto.getContributors(); 173 159 if (songContributors != null) { 160 int songOrder = PUBLISHING_ARTIST_ORDER + 1; 174 161 for (ArtistContributionSummaryDto contributorDto : songContributors) { 175 162 if (contributorDto.getId() == null) continue; 176 163 177 164 Artist contributor = artistService.getArtistById(contributorDto.getId()); 178 165 179 166 // first add to song 180 saveContribution(contributor, songMusicalEntity, contributorDto.getRole());181 167 saveContribution(contributor, songMusicalEntity, songOrder++); 168 182 169 // then add to album if not already added 183 170 if (!albumContributorIds.contains(contributor.getId())) { 184 saveContribution(contributor, album.getMusicalEntities(), contributorDto.getRole());171 saveContribution(contributor, album.getMusicalEntities(), nextAlbumOrder[0]++); 185 172 albumContributorIds.add(contributor.getId()); 186 173 } … … 188 175 } 189 176 } 190 191 192 193 private String saveCoverPhoto(MultipartFile coverPhoto) throws IOException {194 String contentType = coverPhoto.getContentType();195 if (contentType == null || !contentType.startsWith("image/")) {196 throw InvalidFileException.invalidType();197 }198 199 if (coverPhoto.getSize() > MAX_FILE_SIZE) {200 throw InvalidFileException.tooLarge(MAX_FILE_SIZE);201 }202 203 String filename = UUID.randomUUID() + "-" + coverPhoto.getOriginalFilename();204 Path path = Paths.get("uploads/profile-pictures", filename);205 Files.copy(coverPhoto.getInputStream(), path);206 return filename;207 }208 177 } -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/NonAdminUserService.java
re111525 r0519e8d 128 128 p.getId(), 129 129 p.getName(), 130 p.getCover(),130 null, 131 131 p.getCreatedBy().getNonAdminUser().getUser().getFullName(), 132 132 p.getCreatedBy().getNonAdminUser().getUser().getUsername(), -
finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/PlaylistService.java
re111525 r0519e8d 46 46 playlist.getId(), 47 47 playlist.getName(), 48 playlist.getCover(),48 null, 49 49 playlist.getCreatedBy().getNonAdminUser().getUser().getFullName(), 50 50 playlist.getCreatedBy().getNonAdminUser().getUser().getUsername(), … … 111 111 UserNotFoundException::new 112 112 ); 113 Playlist playlist=playlistRepository.save(new Playlist( null,playlistName,listener));113 Playlist playlist=playlistRepository.save(new Playlist(playlistName,listener)); 114 114 if (songId!=null){ 115 115
Note:
See TracChangeset
for help on using the changeset viewer.
