diff --git a/front/package.json b/front/package.json deleted file mode 100644 index deb156a..0000000 --- a/front/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "front", - "version": "0.1.0", - "private": true, - "scripts": { - "serve": "vue-cli-service serve", - "build": "vue-cli-service build", - "lint": "vue-cli-service lint" - }, - "dependencies": { - "axios": "^1.4.0", - "bootstrap": "^4.6.0", - "core-js": "^3.8.3", - "jquery": "^3.6.4", - "popper.js": "^1.16.1", - "vue": "^3.2.13", - "vue-router": "^4.1.6" - }, - "devDependencies": { - "@babel/core": "^7.12.16", - "@babel/eslint-parser": "^7.12.16", - "@vue/cli-plugin-babel": "~5.0.0", - "@vue/cli-plugin-eslint": "~5.0.0", - "@vue/cli-service": "~5.0.0", - "eslint": "^7.32.0", - "eslint-plugin-vue": "^8.0.3" - }, - "eslintConfig": { - "root": true, - "env": { - "node": true - }, - "extends": [ - "plugin:vue/vue3-essential", - "eslint:recommended" - ], - "parserOptions": { - "parser": "@babel/eslint-parser" - }, - "rules": { - "vue/multi-word-component-names": 0 - } - }, - "browserslist": [ - "> 1%", - "last 2 versions", - "not dead", - "not ie 11" - ] -} \ No newline at end of file diff --git a/front/src/components/Header.vue b/front/src/components/Header.vue new file mode 100644 index 0000000..1aa0c75 --- /dev/null +++ b/front/src/components/Header.vue @@ -0,0 +1,48 @@ + + + + + + + \ No newline at end of file diff --git a/front/src/models/Album.js b/front/src/models/Album.js new file mode 100644 index 0000000..33ce386 --- /dev/null +++ b/front/src/models/Album.js @@ -0,0 +1,7 @@ +export default class Album{ + constructor(data) { + this.id = data?.id; + this.albumName = data?.albumName; + this.artistIds = data?.artistIds; + } +} \ No newline at end of file diff --git a/front/src/models/Artist.js b/front/src/models/Artist.js new file mode 100644 index 0000000..c7aedb2 --- /dev/null +++ b/front/src/models/Artist.js @@ -0,0 +1,7 @@ +export default class Artist{ + constructor(data) { + this.id = data?.id; + this.artistName = data?.artistName; + this.albumIds = data?.albumIds; + } +} \ No newline at end of file diff --git a/front/src/models/Song.js b/front/src/models/Song.js new file mode 100644 index 0000000..6ac8eaf --- /dev/null +++ b/front/src/models/Song.js @@ -0,0 +1,8 @@ +export default class Song{ + constructor(data) { + this.id = data?.id; + this.songName = data?.songName; + this.duration = data?.duration; + this.album = data?.album; + } +} \ No newline at end of file diff --git a/front/src/pages/albums.vue b/front/src/pages/albums.vue new file mode 100644 index 0000000..dd36b05 --- /dev/null +++ b/front/src/pages/albums.vue @@ -0,0 +1,408 @@ + + + \ No newline at end of file diff --git a/front/src/pages/artists.vue b/front/src/pages/artists.vue new file mode 100644 index 0000000..0e941ef --- /dev/null +++ b/front/src/pages/artists.vue @@ -0,0 +1,130 @@ + + + \ No newline at end of file diff --git a/front/src/pages/songs.vue b/front/src/pages/songs.vue new file mode 100644 index 0000000..0005da1 --- /dev/null +++ b/front/src/pages/songs.vue @@ -0,0 +1,156 @@ + + + \ No newline at end of file diff --git a/front/src/router/index.js b/front/src/router/index.js new file mode 100644 index 0000000..5813797 --- /dev/null +++ b/front/src/router/index.js @@ -0,0 +1,19 @@ +import artists from "../pages/artists.vue" +import albums from "../pages/albums.vue" +import songs from "../pages/songs.vue" + +import {createRouter, createWebHistory} from "vue-router" + +const routes = [ + {path: '/artists', component: artists}, + {path: '/albums', component: albums}, + {path: '/songs', component: songs}, +] + +const router = createRouter({ + history: createWebHistory(), + linkActiveClass: 'active', + routes +}) + +export default router; \ No newline at end of file diff --git a/front/src/views/AboutView.vue b/front/src/views/AboutView.vue new file mode 100644 index 0000000..571e181 --- /dev/null +++ b/front/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + \ No newline at end of file diff --git a/front/src/views/HomeView.vue b/front/src/views/HomeView.vue new file mode 100644 index 0000000..4c6e037 --- /dev/null +++ b/front/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/src/main/java/ru/ulstu/is/sbapp/Repository/IAlbumRepository.java b/src/main/java/ru/ulstu/is/sbapp/Repository/IAlbumRepository.java index d525634..bfd41fe 100644 --- a/src/main/java/ru/ulstu/is/sbapp/Repository/IAlbumRepository.java +++ b/src/main/java/ru/ulstu/is/sbapp/Repository/IAlbumRepository.java @@ -1,7 +1,15 @@ package ru.ulstu.is.sbapp.Repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import ru.ulstu.is.sbapp.database.model.Album; +import java.util.List; + public interface IAlbumRepository extends JpaRepository { + @Query("select a.albumName as album, s.songName as songs " + + "from Album a " + + "join a.songs s " + + "group by a.id, a.albumName, s.songName") + List getAll(); } diff --git a/src/main/java/ru/ulstu/is/sbapp/Repository/IArtistRepository.java b/src/main/java/ru/ulstu/is/sbapp/Repository/IArtistRepository.java index 5414df4..9aa5127 100644 --- a/src/main/java/ru/ulstu/is/sbapp/Repository/IArtistRepository.java +++ b/src/main/java/ru/ulstu/is/sbapp/Repository/IArtistRepository.java @@ -9,6 +9,6 @@ import ru.ulstu.is.sbapp.database.model.Song; import java.util.List; public interface IArtistRepository extends JpaRepository { - @Query("SELECT DISTINCT a.songs FROM Album a where :artist MEMBER OF a.artists") - List getSongs(@Param("artist") Artist artist); + @Query(value = "SELECT * FROM artist_album", nativeQuery = true) + List getAllArtistAlbum(); } diff --git a/src/main/java/ru/ulstu/is/sbapp/controllers/AlbumController.java b/src/main/java/ru/ulstu/is/sbapp/controllers/AlbumController.java index 49ff8ca..9881ac7 100644 --- a/src/main/java/ru/ulstu/is/sbapp/controllers/AlbumController.java +++ b/src/main/java/ru/ulstu/is/sbapp/controllers/AlbumController.java @@ -1,55 +1,85 @@ package ru.ulstu.is.sbapp.controllers; import jakarta.validation.Valid; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import ru.ulstu.is.sbapp.database.model.Artist; +import ru.ulstu.is.sbapp.database.model.Song; import ru.ulstu.is.sbapp.database.service.AlbumService; -import java.util.ArrayList; import java.util.List; +import java.util.Map; @RestController @RequestMapping("/album") public class AlbumController { private final AlbumService albumService; - @Autowired - public AlbumController(AlbumService albumService){ + + public AlbumController(AlbumService albumService) { this.albumService = albumService; } - @GetMapping("/albums/{id}") - public AlbumDTO getAlbum(@PathVariable Long id) { + + @GetMapping("/{id}") + public AlbumDTO getAlbum(@PathVariable Long id){ return new AlbumDTO(albumService.findAlbum(id)); } - @GetMapping("/albums") - public List getAlbums() { - return albumService.findAllAlbums().stream().map(AlbumDTO::new).toList(); + + @GetMapping + public List getAlbums(){ + return albumService.findAllAlbums().stream() + .map(AlbumDTO::new) + .toList(); } - @PostMapping("/albums") - public ResponseEntity createAlbum(@RequestBody @Valid AlbumDTO albumDTO){ - List list = new ArrayList<>(); - for (ArtistDTO art: - albumDTO.getArtistList()) { - list.add(art.getId()); - } - return new ResponseEntity<> - (new AlbumDTO(albumService.addAlbum - (albumDTO.getAlbumName(),list)), HttpStatus.OK); + + @PostMapping + public AlbumDTO createAlbum(@RequestBody @Valid AlbumDTO albumDTO){ + return new AlbumDTO(albumService.addAlbum(albumDTO.getAlbumName())); } - @PutMapping("/albums/{id}") - public ResponseEntity updateAlbum(@RequestBody @Valid AlbumDTO albumDTO){ - List list = new ArrayList<>(); - for (ArtistDTO art: - albumDTO.getArtistList()) { - list.add(art.getId()); - } - return new ResponseEntity<> - (new AlbumDTO(albumService.updateAlbum - (albumDTO.getId(), albumDTO.getAlbumName(), list)), HttpStatus.OK); + + @PutMapping("/{id}") + public AlbumDTO updateAlbum(@PathVariable Long id, @RequestBody @Valid AlbumDTO albumDTO){ + return new AlbumDTO(albumService.updateAlbum(id, albumDTO.getAlbumName())); } - @DeleteMapping("/albums/{id}") + + @DeleteMapping("/{id}") public AlbumDTO deleteAlbum(@PathVariable Long id){ return new AlbumDTO(albumService.deleteAlbum(id)); } + + @GetMapping("/{albumId}/songs") + public ResponseEntity> getSongsFromAlbum(@PathVariable Long albumId) { + List songs = albumService.getSongFromAlbum(albumId); + return ResponseEntity.ok(songs); + } + + @GetMapping("/{albumId}/getAllArtists") + public ResponseEntity> getArtistInAlbum(@PathVariable Long albumId){ + List artists = albumService.getArtistInAlbum(albumId); + return ResponseEntity.ok(artists); + } + + @GetMapping("/getSongsUndefined") + public ResponseEntity> getSongsFromUndefinedAlbum(){ + List songs = albumService.getSongsUndefined(); + return ResponseEntity.ok(songs); + } + + @PostMapping("/{id}/addSongs") + public void addSongToAlbum(@PathVariable Long id, @RequestBody @Valid List songsIds){ + albumService.addSongToAlbum(id, songsIds); + } + + @DeleteMapping("deleteSongFromAlbum/{id}") + public void deleteSongFromAlbum(@PathVariable Long id){ + albumService.deleteSongFromAlbum(id); + } + + @PostMapping("/{id}/addArtistToAlbum") + public void addArtistToAlbum(@PathVariable Long id, @RequestBody @Valid List artistIds){ + albumService.addArtistToAlbum(id, artistIds); + } + @GetMapping("/getAll") + public Map> getAll(){ + return albumService.getAll(); + } } diff --git a/src/main/java/ru/ulstu/is/sbapp/controllers/AlbumDTO.java b/src/main/java/ru/ulstu/is/sbapp/controllers/AlbumDTO.java index d7d8ad1..e26aa39 100644 --- a/src/main/java/ru/ulstu/is/sbapp/controllers/AlbumDTO.java +++ b/src/main/java/ru/ulstu/is/sbapp/controllers/AlbumDTO.java @@ -1,41 +1,38 @@ package ru.ulstu.is.sbapp.controllers; - -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Null; import ru.ulstu.is.sbapp.database.model.Album; import java.util.List; public class AlbumDTO { - @NotNull(message = "Id can't be null") - private final Long id; - @NotBlank(message = "Name can't be null or empty") - private final String albumName; - @Null - private final List artistList; + private Long id; + private String albumName; + private List artistIds; + public AlbumDTO(){ + + } public AlbumDTO(Album album){ this.id = album.getId(); this.albumName = album.getAlbumName(); - this.artistList = album.getArtists().stream().map(ArtistDTO::new).toList(); + this.artistIds = album.getArtistIds(); } - public AlbumDTO(Long id, String albumName, List artistList){ - this.id = id; - this.albumName = albumName; - this.artistList = artistList; - } - public Long getId() { + + public Long getId(){ return id; } + public String getAlbumName(){ return albumName; } - public List getArtistList(){ - return artistList; + + public void setId(Long id){ + this.id = id; } - @JsonProperty(access = JsonProperty.Access.READ_ONLY) - public String getData() { - return String.format("%s %s %s", id, albumName, artistList.toString()); + + public void setAlbumName(String name){ + this.albumName = name; + } + + public List getArtistIds(){ + return artistIds; } } diff --git a/src/main/java/ru/ulstu/is/sbapp/controllers/ArtistController.java b/src/main/java/ru/ulstu/is/sbapp/controllers/ArtistController.java index 7d02e18..c0f724f 100644 --- a/src/main/java/ru/ulstu/is/sbapp/controllers/ArtistController.java +++ b/src/main/java/ru/ulstu/is/sbapp/controllers/ArtistController.java @@ -1,9 +1,6 @@ package ru.ulstu.is.sbapp.controllers; import jakarta.validation.Valid; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import ru.ulstu.is.sbapp.database.service.ArtistService; @@ -13,32 +10,45 @@ import java.util.List; @RequestMapping("/artist") public class ArtistController { private final ArtistService artistService; - @Autowired - public ArtistController(ArtistService artistService){ + + public ArtistController(ArtistService artistService) { this.artistService = artistService; } - @GetMapping("/artists/{id}") - public ArtistDTO getArtist(@PathVariable Long id) { + + @GetMapping("/{id}") + public ArtistDTO getArtist(@PathVariable Long id){ return new ArtistDTO(artistService.findArtist(id)); } - @GetMapping("/artists") - public List getArtists() { + + @GetMapping + public List getArtist(){ return artistService.findAllArtists().stream() .map(ArtistDTO::new) .toList(); } - @PostMapping("/artists") - public ResponseEntity createArtist(@RequestBody @Valid ArtistDTO artistDTO) { - return new ResponseEntity<>(new ArtistDTO(artistService.addArtist(artistDTO.getArtistName(), artistDTO.getGenre())), HttpStatus.OK); + + @PostMapping + public ArtistDTO createArtist(@RequestBody @Valid ArtistDTO artistDTO){ + return new ArtistDTO(artistService.addArtist(artistDTO.getArtistName(), artistDTO.getGenre())); } - @PutMapping("/artists/{id}") - public ResponseEntity updateArtist(@RequestBody @Valid ArtistDTO artistDTO) { - return new ResponseEntity<>(new ArtistDTO(artistService.updateArtist(artistDTO.getId(), artistDTO.getArtistName(), artistDTO.getGenre())), HttpStatus.OK); + @PutMapping("/{id}") + public ArtistDTO updateArtist(@PathVariable Long id, @RequestBody @Valid ArtistDTO artistDTO){ + return new ArtistDTO(artistService.updateArtist(id, artistDTO.getArtistName(), artistDTO.getGenre())); } - @DeleteMapping("/artists/{id}") - public ArtistDTO deleteArtist(@PathVariable Long id) { + @DeleteMapping("/{id}") + public ArtistDTO deleteArtist(@PathVariable Long id){ return new ArtistDTO(artistService.deleteArtist(id)); } + + @GetMapping("/getAllArtistAlbum") + public List getAllArtistAlbum(){ + return artistService.getAllArtistAlbum(); + } + + @PostMapping("/{id}/addArtistToAlbum") + public void addArtistToAlbum(@PathVariable Long id, @RequestBody @Valid List groupsIds){ + artistService.addArtistToAlbum(id, groupsIds); + } } diff --git a/src/main/java/ru/ulstu/is/sbapp/controllers/ArtistDTO.java b/src/main/java/ru/ulstu/is/sbapp/controllers/ArtistDTO.java index 0877a02..c851f9b 100644 --- a/src/main/java/ru/ulstu/is/sbapp/controllers/ArtistDTO.java +++ b/src/main/java/ru/ulstu/is/sbapp/controllers/ArtistDTO.java @@ -1,35 +1,45 @@ package ru.ulstu.is.sbapp.controllers; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; import ru.ulstu.is.sbapp.database.model.Artist; import java.util.List; public class ArtistDTO { - @NotNull(message = "Id can't be null") - private final Long id; - @NotBlank(message = "Name can't be null or empty") - private final String artistName; - @NotBlank(message = "Genre can't be null or empty") - private final String genre; + private Long id; + private String artistName; + private String genre; + private List albumIds; + public ArtistDTO(){ + + } public ArtistDTO(Artist artist){ this.id = artist.getId(); this.artistName = artist.getArtistName(); this.genre = artist.getGenre(); + this.albumIds = artist.getAlbumIds(); } - public ArtistDTO(Long id, String artistName, String genre) { - this.id = id; - this.artistName = artistName; - this.genre = genre; - } - public Long getId() { + + public Long getId(){ return id; } - public String getArtistName() { + public void setId(Long id){ + this.id = id; + } + + public String getArtistName(){ return artistName; } - public String getGenre() { + + public String getGenre(){ return genre; } -} + + public void setGenre(String genre){ + this.genre = genre; + } + + public List getAlbumIds(){ + return albumIds; + } + +} \ No newline at end of file diff --git a/src/main/java/ru/ulstu/is/sbapp/controllers/SongController.java b/src/main/java/ru/ulstu/is/sbapp/controllers/SongController.java index 2e497f4..7267a95 100644 --- a/src/main/java/ru/ulstu/is/sbapp/controllers/SongController.java +++ b/src/main/java/ru/ulstu/is/sbapp/controllers/SongController.java @@ -1,10 +1,8 @@ package ru.ulstu.is.sbapp.controllers; import jakarta.validation.Valid; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import ru.ulstu.is.sbapp.database.service.AlbumService; import ru.ulstu.is.sbapp.database.service.SongService; import java.util.List; @@ -13,34 +11,45 @@ import java.util.List; @RequestMapping("/song") public class SongController { private final SongService songService; - @Autowired - public SongController(SongService songService){ + private final AlbumService albumService; + + public SongController(SongService songService, AlbumService albumService) { this.songService = songService; + this.albumService = albumService; } - @GetMapping("/songs/{id}") - public SongDTO getSong(@PathVariable Long id) { + + @GetMapping("/{id}") + public SongDTO getSong(@PathVariable Long id){ return new SongDTO(songService.findSong(id)); } - @GetMapping("/songs") - public List getSongs() { + + @GetMapping + public List getSongs(){ return songService.findAllSongs().stream() .map(SongDTO::new) .toList(); } - @PostMapping("/songs") - public ResponseEntity createSong(@RequestBody @Valid SongDTO songDTO) { - return new ResponseEntity<> - (new SongDTO(songService.addSong - (songDTO.getSongName(), songDTO.getDuration(), songDTO.getAlbum().getId())), HttpStatus.OK); + + @PostMapping + public SongDTO createSong(@RequestBody @Valid SongDTO songDTO){ + return new SongDTO(songService.addSong(songDTO.getSongName(), songDTO.getDuration())); } - @PutMapping("/song/{id}") - public ResponseEntity updateSong(@RequestBody @Valid SongDTO songDTO) { - return new ResponseEntity<>(new SongDTO(songService.updateSong(songDTO.getId(), songDTO.getSongName(), songDTO.getDuration(), songDTO.getAlbum().getId())), HttpStatus.OK); + @PutMapping("/{id}") + public SongDTO updateSong(@PathVariable Long id, @RequestBody @Valid SongDTO songDTO) { + return new SongDTO(songService.updateSong(id, songDTO.getSongName(), songDTO.getDuration())); } - @DeleteMapping("/songs/{id}") - public SongDTO deleteSong(@PathVariable Long id) { + @DeleteMapping("/{id}") + public SongDTO deleteSong(@PathVariable Long id){ return new SongDTO(songService.deleteSong(id)); } + + @GetMapping("/albums") + public List getAlbums() { + return albumService.findAllAlbums().stream() + .map(AlbumDTO::new) + .toList(); + } + } diff --git a/src/main/java/ru/ulstu/is/sbapp/controllers/SongDTO.java b/src/main/java/ru/ulstu/is/sbapp/controllers/SongDTO.java index ad23c5d..e6ab665 100644 --- a/src/main/java/ru/ulstu/is/sbapp/controllers/SongDTO.java +++ b/src/main/java/ru/ulstu/is/sbapp/controllers/SongDTO.java @@ -1,45 +1,57 @@ package ru.ulstu.is.sbapp.controllers; -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; import ru.ulstu.is.sbapp.database.model.Song; public class SongDTO { - @NotNull(message = "Id can't be null") - private final Long id; - @NotBlank(message = "Name can't be null or empty") - private final String songName; - @NotNull(message = "Album can't be null") - private final AlbumDTO album; - @NotBlank(message = "Duration can't be null or empty") - private final Double duration; - public SongDTO(Song song){ + private Long id; + private String songName; + private Double duration; + private Long albumId; + private String albumName; + + public SongDTO() { + } + public SongDTO(Song song) { this.id = song.getId(); this.songName = song.getSongName(); this.duration = song.getDuration(); - this.album = new AlbumDTO(song.getAlbum()); + if(song.getAlbum() != null){ + this.albumName = song.getAlbum().getAlbumName(); + } } - public SongDTO(Long id, String songName, Double duration, AlbumDTO album){ - this.id = id; - this.songName = songName; - this.duration = duration; - this.album = album; + + public String getAlbumName() { + return albumName; } - public Long getId() { + public Long getId(){ return id; } + public String getSongName(){ return songName; } + public Double getDuration(){ return duration; } - public AlbumDTO getAlbum() { - return album; + + public Long getAlbumId(){ + return albumId; } - @JsonProperty(access = JsonProperty.Access.READ_ONLY) - public String getData() { - return String.format("%s %s %s %s", id, songName, duration, album.getAlbumName()); + + public void setAlbumId(long id){ + this.albumId = id; + } + + public void setId(long id){ + this.id = id; + } + + public void setSongName(String name){ + this.songName = name; + } + + public void setDuration(Double duration){ + this.duration = duration; } } diff --git a/src/main/java/ru/ulstu/is/sbapp/database/model/Album.java b/src/main/java/ru/ulstu/is/sbapp/database/model/Album.java index 7e27db2..b4b2adb 100644 --- a/src/main/java/ru/ulstu/is/sbapp/database/model/Album.java +++ b/src/main/java/ru/ulstu/is/sbapp/database/model/Album.java @@ -1,93 +1,52 @@ package ru.ulstu.is.sbapp.database.model; +import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; -import jakarta.validation.constraints.NotBlank; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; @Entity +@Table(name = "albums") public class Album { @Id - @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @NotBlank private String albumName; - @OneToMany(fetch = FetchType.EAGER,mappedBy = "album") + + @JsonManagedReference + @OneToMany(fetch = FetchType.EAGER, mappedBy = "album") private List songs; - @ManyToMany(fetch = FetchType.EAGER) - @JoinTable(name = "albums_artists", - joinColumns = @JoinColumn(name = "album_fk"), - inverseJoinColumns = @JoinColumn(name = "artist_fk")) + + @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinTable(name = "artist_album", + joinColumns = {@JoinColumn(name = "album_id")}, + inverseJoinColumns = {@JoinColumn(name = "artist_id")}) private List artists; - public Album(){} - public Album(String albumName){ - this.albumName = albumName; - } - public Long getId() { - return id; - } - public String getAlbumName(){ - return albumName; + + public Album() { + this.songs = new ArrayList<>(); } - public void setAlbumName(String albumName) { - this.albumName = albumName; - } - public List getArtists(){ - return artists; - } - public void addArtist(Artist artist){ - if(artists==null) - artists=new ArrayList<>(); - artists.add(artist); - artist.addAlbum(this); - } - public void setArtists(List art){ - this.artists=art; - } - public void removeArtist(Artist artist){ - if(artists!=null){ - artists.remove(artist); - artist.removeAlbum(this); - } - } - public List getSongs(){ - return songs; - } - public void addSong(Song song){ - if(songs==null) - songs = new ArrayList<>(); - songs.add(song); - } - public void removeSong(Song song){ - if(song!=null) - songs.remove(song); + public Album(String name) { + this.albumName = name; + this.songs = new ArrayList<>(); } + + public Long getId() { return id; } + public String getAlbumName() { return albumName; } + public void setAlbumName(String name) { this.albumName = name; } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Album album = (Album) o; - if(!this.id.equals(album.getId())) return false; - if(!this.albumName.equals(album.getAlbumName())) return false; - if(artists.size() != album.getArtists().size()) return false; - if(artists.size()>0){ - for (Artist art: - artists) { - boolean check = false; - for (Artist artAlb: - album.getArtists()) { - if(art.equals(artAlb)) - check = true; - } - if(!check) - return false; - } - } return Objects.equals(id, album.id); } + @Override public int hashCode() { return Objects.hash(id); @@ -97,8 +56,48 @@ public class Album { public String toString() { return "Album{" + "id=" + id + - ", Name='" + albumName + '\'' + - "Artists:" + (artists == null ? "[]" : artists.toString()) + + ", name='" + albumName + '\'' + '}'; } + + public void setSong(Song song){ + this.songs.add(song); + if(song.getAlbum() != this){ + song.setAlbum(this); + } + } + public List getSongs(){ + return songs; + } + + public void setSongs(List songs) { + this.songs = songs; + } + + public List getArtists(){ + return artists; + } + + public void setArtists(List artists) { + this.artists = artists; + } + + public void addArtist(Artist artist) { + artists.add(artist); + artist.getAlbums().add(this); + } + + public List getArtistIds() { + if (artists.isEmpty()) { + return Collections.emptyList(); + } else { + List artistIds = new ArrayList<>(); + for (Artist artist : artists) { + if (!artistIds.contains(artist.getId())) { + artistIds.add(artist.getId()); + } + } + return artistIds; + } + } } diff --git a/src/main/java/ru/ulstu/is/sbapp/database/model/Artist.java b/src/main/java/ru/ulstu/is/sbapp/database/model/Artist.java index 6b82e86..8bf0bfe 100644 --- a/src/main/java/ru/ulstu/is/sbapp/database/model/Artist.java +++ b/src/main/java/ru/ulstu/is/sbapp/database/model/Artist.java @@ -1,66 +1,50 @@ package ru.ulstu.is.sbapp.database.model; +import com.fasterxml.jackson.annotation.JsonBackReference; import jakarta.persistence.*; -import jakarta.validation.constraints.NotBlank; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; @Entity +@Table(name = "artists") public class Artist { @Id - @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @NotBlank private String artistName; - @NotBlank private String genre; - @ManyToMany(fetch = FetchType.EAGER,mappedBy = "artists") - private List albums; + @JsonBackReference + @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.EAGER) + @JoinTable(name = "artist_album", + joinColumns = {@JoinColumn(name = "artist_id")}, + inverseJoinColumns = {@JoinColumn(name = "album_id")}) + private List albums = new ArrayList<>(); - public Artist(){} - public Artist(String artistName, String genre){ - this.artistName = artistName; + public Artist() { + } + + public Artist(String name, String genre) { + this.artistName = name; this.genre = genre; } - public Long getId() { - return id; - } - public String getArtistName(){ - return artistName; - } - public void setArtistName(String value){ - artistName=value; - } - public String getGenre(){ - return genre; - } - public void setGenre(String value){ - genre=value; - } - public List getAlbums(){ - return albums; - } - public void addAlbum(Album album){ - if(albums==null) - albums = new ArrayList<>(); - albums.add(album); - } - public void removeAlbum(Album album){ - if(album!=null) - albums.remove(album); - } + + public Long getId() { return id; } + public String getArtistName() { return artistName; } + public void setArtistName(String name) { this.artistName = name; } + public String getGenre() { return genre; } + public void setGenre(String genre) { this.genre = genre; } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Artist artist = (Artist) o; - if(!this.artistName.equals(artist.getArtistName())) return false; - if(!this.genre.equals(artist.getGenre())) return false; - if(this.id != artist.getId()) return false; return Objects.equals(id, artist.id); } + @Override public int hashCode() { return Objects.hash(id); @@ -70,8 +54,29 @@ public class Artist { public String toString() { return "Artist{" + "id=" + id + - ", Name='" + artistName + '\'' + - ", Genre='" + genre + '\'' + + ", name='" + artistName + '\'' + '}'; } + + public List getAlbums(){ + return albums; + } + + public void setAlbums(List albums) { + this.albums = albums; + } + + public List getAlbumIds() { + if (albums.isEmpty()) { + return Collections.emptyList(); + } else { + List albumIds = new ArrayList<>(); + for (Album album : albums) { + if (!albumIds.contains(album.getId())) { + albumIds.add(album.getId()); + } + } + return albumIds; + } + } } diff --git a/src/main/java/ru/ulstu/is/sbapp/database/model/Song.java b/src/main/java/ru/ulstu/is/sbapp/database/model/Song.java index 4915ca1..0e0c3bd 100644 --- a/src/main/java/ru/ulstu/is/sbapp/database/model/Song.java +++ b/src/main/java/ru/ulstu/is/sbapp/database/model/Song.java @@ -1,5 +1,6 @@ package ru.ulstu.is.sbapp.database.model; +import com.fasterxml.jackson.annotation.JsonBackReference; import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -7,55 +8,41 @@ import jakarta.validation.constraints.NotNull; import java.util.Objects; @Entity -@Table(name = "song") +@Table(name = "songs") public class Song { @Id - @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @NotBlank private String songName; - @NotBlank private Double duration; - @NotNull - @ManyToOne + + @JsonBackReference + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "album_id", nullable = true) private Album album; - public Song(){} - public Song(String songName, Double duration){ - this.songName=songName; - this.duration=duration; - } - public Long getId() { - return id; - } - public String getSongName(){ - return songName; + + public Song() { } - public void setSongName(String songName) { + public Song(String songName, Double duration) { this.songName = songName; - } - public Double getDuration(){return duration;} - public void setDuration(Double duration) { this.duration = duration; } - public Album getAlbum() { - return album; - } - public void setAlbum(Album value){ - album=value; - album.addSong(this); - } + + public Long getId() { return id; } + public String getSongName() { return songName; } + public void setSongName(String songName) { this.songName = songName; } + public Double getDuration() { return duration;} + public void setDuration(Double duration) { this.duration = duration; } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Song song = (Song) o; - if(!this.id.equals(song.getId())) return false; - if(!this.songName.equals(song.getSongName())) return false; - if(!this.duration.equals(song.getDuration())) return false; - if(!this.album.getId().equals(song.getAlbum().getId())) return false; return Objects.equals(id, song.id); } + @Override public int hashCode() { return Objects.hash(id); @@ -63,11 +50,29 @@ public class Song { @Override public String toString() { + String albumStr = (album != null) ? album.getAlbumName() : "No Album"; return "Song{" + "id=" + id + ", songName='" + songName + '\'' + - ", Duration='" + duration + '\'' + + ", duration='" + duration + '\'' + + ", album='" + albumStr + '\'' + '}'; } + + public Album getAlbum() { + return album; + } + + public void setAlbum(Album album) { + if (this.album != album) { + if (this.album != null) { + this.album.getSongs().remove(this); + } + this.album = album; + if (album != null && !album.getSongs().contains(this)) { + album.getSongs().add(this); + } + } + } } diff --git a/src/main/java/ru/ulstu/is/sbapp/database/service/AlbumService.java b/src/main/java/ru/ulstu/is/sbapp/database/service/AlbumService.java index 59489e6..7592c6e 100644 --- a/src/main/java/ru/ulstu/is/sbapp/database/service/AlbumService.java +++ b/src/main/java/ru/ulstu/is/sbapp/database/service/AlbumService.java @@ -1,73 +1,60 @@ package ru.ulstu.is.sbapp.database.service; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import ru.ulstu.is.sbapp.Repository.IAlbumRepository; import ru.ulstu.is.sbapp.database.model.Album; import ru.ulstu.is.sbapp.database.model.Artist; -import ru.ulstu.is.sbapp.database.util.validation.ValidatorUtil; +import ru.ulstu.is.sbapp.database.model.Song; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; @Service public class AlbumService { - private final IAlbumRepository albumRepository; - private final ValidatorUtil validatorUtil; - private final ArtistService artistService; - public AlbumService(IAlbumRepository albumRepository, ValidatorUtil validatorUtil, ArtistService artistService){ + private final SongService songService; + private final ArtistService artistService; + + public AlbumService(IAlbumRepository albumRepository, SongService songService, @Lazy ArtistService artistService) { this.albumRepository = albumRepository; - this.validatorUtil = validatorUtil; + this.songService = songService; this.artistService = artistService; } @Transactional - public Album addAlbum(String albumName, List artistsId) { - final Album album = new Album(albumName); - if(artistsId.size() > 0 ) - { - for (Long id: - artistsId) { - Artist art = artistService.findArtist(id); - album.addArtist(art); - } + public Album addAlbum(String name){ + if (!StringUtils.hasText(name)) { + throw new IllegalArgumentException("Album name is null or empty"); } - else - album.setArtists(new ArrayList<>()); - validatorUtil.validate(album); - + final Album album = new Album(name); return albumRepository.save(album); } - @Transactional(readOnly = true) - public Album findAlbum(Long id) { + @Transactional(readOnly = true) + public Album findAlbum(Long id){ final Optional album = albumRepository.findById(id); return album.orElseThrow(() -> new AlbumNotFoundException(id)); } + @Transactional(readOnly = true) public List findAllAlbums() { return albumRepository.findAll(); } @Transactional - public Album updateAlbum(Long id, String albumName, List artistIds) { - final Album currentAlbum = findAlbum(id); - currentAlbum.setAlbumName(albumName); - if(artistIds.size()>0) - { - currentAlbum.getArtists().clear(); - for (Long ArtId: - artistIds) { - Artist art = artistService.findArtist(ArtId); - currentAlbum.addArtist(art); - } + public Album updateAlbum(Long id, String name) { + if (!StringUtils.hasText(name)) { + throw new IllegalArgumentException("Album name is null or empty"); } - else - currentAlbum.getArtists().clear(); - validatorUtil.validate(currentAlbum); + final Album currentAlbum = findAlbum(id); + currentAlbum.setAlbumName(name); return albumRepository.save(currentAlbum); } @@ -82,4 +69,72 @@ public class AlbumService { public void deleteAllAlbums() { albumRepository.deleteAll(); } + + @Transactional + public List getSongFromAlbum(Long albumId){ + Optional albumOptional = albumRepository.findById(albumId); + if (albumOptional.isPresent()) { + Album album = albumOptional.get(); + return album.getSongs(); + } else { + throw new IllegalArgumentException("Album not found with id: " + albumId); + } + } + + @Transactional + public List getArtistInAlbum(Long albumId){ + Optional albumOptional = albumRepository.findById(albumId); + if (albumOptional.isPresent()) { + Album album = albumOptional.get(); + return album.getArtists(); + } else { + throw new IllegalArgumentException("Album not found with id: " + albumId); + } + } + + @Transactional + public List getSongsUndefined(){ + List songs = new ArrayList<>(); + for(Song song : songService.findAllSongs()){ + if(song.getAlbum() == null){ + songs.add(song); + } + } + return songs; + } + + @Transactional + public void addSongToAlbum(Long albumId, List songIds){ + final Album currentAlbum = findAlbum(albumId); + for(Long songId : songIds) { + songService.findSong(songId).setAlbum(currentAlbum); + } + albumRepository.save(currentAlbum); + } + + @Transactional + public void deleteSongFromAlbum(Long id){ + songService.findSong(id).setAlbum(null); + } + + @Transactional + public void addArtistToAlbum(Long albumId, List artistIds){ + final Album currentAlbum = findAlbum(albumId); + currentAlbum.setArtists(new ArrayList<>()); + for(Long artistId : artistIds) { + currentAlbum.getArtists().add(artistService.findArtist(artistId)); + } + albumRepository.save(currentAlbum); + } + + @Transactional + public Map> getAll(){ + return albumRepository.getAll().stream() + .collect( + Collectors.groupingBy( + o -> (String) o[0], + Collectors.mapping( o -> (String) o[1], Collectors.toList() ) + ) + ); + } } diff --git a/src/main/java/ru/ulstu/is/sbapp/database/service/ArtistService.java b/src/main/java/ru/ulstu/is/sbapp/database/service/ArtistService.java index 8b5f454..1d0b64f 100644 --- a/src/main/java/ru/ulstu/is/sbapp/database/service/ArtistService.java +++ b/src/main/java/ru/ulstu/is/sbapp/database/service/ArtistService.java @@ -2,33 +2,35 @@ package ru.ulstu.is.sbapp.database.service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import ru.ulstu.is.sbapp.Repository.IArtistRepository; import ru.ulstu.is.sbapp.database.model.Artist; -import ru.ulstu.is.sbapp.database.util.validation.ValidatorUtil; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @Service public class ArtistService { - private final IArtistRepository artistRepository; - private final ValidatorUtil validatorUtil; + private final AlbumService albumService; - public ArtistService(IArtistRepository artistRepository, - ValidatorUtil validatorUtil) { + public ArtistService(IArtistRepository artistRepository, AlbumService albumService) { this.artistRepository = artistRepository; - this.validatorUtil = validatorUtil; + this.albumService = albumService; } + @Transactional - public Artist addArtist(String artistName, String genre) { + public Artist addArtist(String artistName, String genre){ + if (!StringUtils.hasText(artistName) || !StringUtils.hasText(genre)) { + throw new IllegalArgumentException("Artist name or genre is null or empty"); + } final Artist artist = new Artist(artistName, genre); - validatorUtil.validate(artist); return artistRepository.save(artist); } - @Transactional(readOnly = true) - public Artist findArtist(Long id) { + @Transactional(readOnly = true) + public Artist findArtist(Long id){ final Optional artist = artistRepository.findById(id); return artist.orElseThrow(() -> new ArtistNotFoundException(id)); } @@ -39,17 +41,19 @@ public class ArtistService { } @Transactional - public Artist updateArtist(Long id, String artistName, String genre) { + public Artist updateArtist(Long id, String name, String genre) { + if (!StringUtils.hasText(name) || !StringUtils.hasText(genre)) { + throw new IllegalArgumentException("Artist name or genre is null or empty"); + } final Artist currentArtist = findArtist(id); - currentArtist.setArtistName(artistName); - currentArtist.setGenre(genre); - validatorUtil.validate(currentArtist); + currentArtist.setArtistName(name); return artistRepository.save(currentArtist); } @Transactional public Artist deleteArtist(Long id) { final Artist currentArtist = findArtist(id); + currentArtist.getAlbums().clear(); // Удаляем все связи с альбомами artistRepository.delete(currentArtist); return currentArtist; } @@ -58,4 +62,19 @@ public class ArtistService { public void deleteAllArtists() { artistRepository.deleteAll(); } + + @Transactional + public List getAllArtistAlbum(){ + return artistRepository.getAllArtistAlbum(); + } + + @Transactional + public void addArtistToAlbum(Long artistId, List albumIds){ + final Artist currentArtist = findArtist(artistId); + currentArtist.setAlbums(new ArrayList<>()); + for(Long albumId : albumIds) { + currentArtist.getAlbums().add(albumService.findAlbum(albumId)); + } + artistRepository.save(currentArtist); + } } diff --git a/src/main/java/ru/ulstu/is/sbapp/database/service/SongService.java b/src/main/java/ru/ulstu/is/sbapp/database/service/SongService.java index edbb8eb..3f4d54e 100644 --- a/src/main/java/ru/ulstu/is/sbapp/database/service/SongService.java +++ b/src/main/java/ru/ulstu/is/sbapp/database/service/SongService.java @@ -1,11 +1,11 @@ package ru.ulstu.is.sbapp.database.service; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import ru.ulstu.is.sbapp.Repository.ISongRepository; -import ru.ulstu.is.sbapp.database.model.Album; import ru.ulstu.is.sbapp.database.model.Song; -import ru.ulstu.is.sbapp.database.util.validation.ValidatorUtil; import java.util.List; import java.util.Optional; @@ -14,25 +14,23 @@ import java.util.Optional; public class SongService { private final ISongRepository songRepository; - private final ValidatorUtil validatorUtil; private final AlbumService albumService; - public SongService(ISongRepository songRepository, ValidatorUtil validatorUtil, AlbumService albumService){ + public SongService(ISongRepository songRepository, @Lazy AlbumService albumService) { this.songRepository = songRepository; - this.validatorUtil = validatorUtil; this.albumService = albumService; } @Transactional - public Song addSong(String songName, Double duration, Long albumId){ - final Song song = new Song(songName,duration); - Album curAlbum = albumService.findAlbum(albumId); - song.setAlbum(curAlbum); - validatorUtil.validate(song); + public Song addSong(String songName, Double duration){ + if (!StringUtils.hasText(songName) || !StringUtils.hasText(String.valueOf(duration))) { + throw new IllegalArgumentException("Song name or duration is null or empty"); + } + final Song song = new Song(songName, duration); return songRepository.save(song); } - @Transactional(readOnly = true) + @Transactional(readOnly = true) public Song findSong(Long id) { final Optional song = songRepository.findById(id); return song.orElseThrow(() -> new SongNotFoundException(id)); @@ -44,13 +42,13 @@ public class SongService { } @Transactional - public Song updateSong(Long id, String songName, Double duration, Long albumId) { + public Song updateSong(Long id, String name, Double duration) { + if (!StringUtils.hasText(name) || !StringUtils.hasText(String.valueOf(duration))) { + throw new IllegalArgumentException("Song name or duration is null or empty"); + } final Song currentSong = findSong(id); - currentSong.setSongName(songName); + currentSong.setSongName(name); currentSong.setDuration(duration); - Album curAlbum = albumService.findAlbum(albumId); - currentSong.setAlbum(curAlbum); - validatorUtil.validate(currentSong); return songRepository.save(currentSong); } @@ -62,7 +60,18 @@ public class SongService { } @Transactional - public void deleteAllSongs() { + public void deleteAllSong() { songRepository.deleteAll(); } + +// @Transactional +// public void AddSongToAlbum(Long idSong, Long idAlbum){ +// Song song = findSong(idSong); +// Album album = em.find(Album.class, idAlbum); +// if (album == null || song == null) { +// throw new EntityNotFoundException("Album or Song not found"); +// } +// song.setAlbum(album); +// em.merge(song); +// } }