Compare commits

..

2 Commits

Author SHA1 Message Date
9787e46afa lab4 2023-06-01 15:51:35 +04:00
f1975493d3 4лаб 2023-05-25 08:06:05 +04:00
24 changed files with 678 additions and 462 deletions

View File

@ -19,6 +19,8 @@ dependencies {
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5'
implementation 'org.jetbrains:annotations:24.0.0'
implementation 'org.jetbrains:annotations:24.0.0'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.hibernate.validator:hibernate-validator'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

View File

@ -1,68 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>LabWork04</title>
<script src="/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css">
</head>
<body class="bg-light">
<div id="like_button_container"></div>
<!-- <div class="container">-->
<!-- <div class="py-5 text-center"><h2>Лабораторная работа 2</h2></div>-->
<!-- <div class="row">-->
<!-- <div>-->
<!-- <form>-->
<!-- <div class="row">-->
<!-- <div class="col-md-6 mb-3">-->
<!-- <label for="input1">Значение 1 (string или double)</label>-->
<!-- <input class="form-control" id="input1" placeholder="Введите значение 1">-->
<!-- </div>-->
<!-- <div class="col-md-6 mb-3">-->
<!-- <label for="input1">Значение 2 (string или double)</label>-->
<!-- <input class="form-control" id="input2" placeholder="Введите значение 2">-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="row">-->
<!-- <div class="form-group">-->
<!-- <label for="operator">Выберите функцию</label>-->
<!-- <select class="form-control" id="operator">-->
<!-- <option value>Выбрать...</option>-->
<!-- <option value="Func1">(string, double)Сумма</option>-->
<!-- <option value="Func2">(double)Минимум, (string)Сумма в верхний регистр</option>-->
<!-- <option value="Func3">(double)Mаксимум, (string)Разделить</option>-->
<!-- <option value="Func4">(double)Число 1 в степени числа 2, (string)Сумма в нижний регистр</option>-->
<!-- </select>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="row">-->
<!-- <div class="form-group">-->
<!-- <label for="operator">Выберите тип данных</label>-->
<!-- <select class="form-control" id="Type">-->
<!-- <option value>Выбрать...</option>-->
<!-- <option value="str">String</option>-->
<!-- <option value="double">Double</option>-->
<!-- </select>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="row">-->
<!-- <div class="form-group">-->
<!-- <label for="result">Результат</label>-->
<!-- <input type="text" class="form-control result" id="result" readonly>-->
<!-- <hr class="mb-4">-->
<!-- <button type="button" class="btn btn-primary btn-block" onclick="calculate()">Посчитать</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </form>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<script src = "script.js"></script>
<!-- Загрузим React. -->
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<!-- Загрузим наш React-компонент. -->
<script src="react.js"></script>
</body>
</html>

View File

@ -0,0 +1,137 @@
<template>
<div v-if="currentAlbum" class="edit-form">
<h4>Album</h4>
<form>
<div class="form-group">
<label for="albumName">Album Name</label>
<input type="text" class="form-control" id="albumName"
v-model="currentAlbum.albumName"
/>
</div>
<div class="form-group">
<label >Song</label>
<div>
<select v-model="currentAlbum.song">
<option v-for="blog in songs" :key="blog.id" :value="blog">{{ blog.nickName }}</option>
</select>
</div>
</div>
<div class="form-group prokrutka">
<label >Artists</label>
<div>
<template v-for="art in artists" v-bind:key="art.id">
<input type="checkbox" v-bind:value="art" v-model="currentAlbum.artistList"/>
<label>{{ art.albumName }}</label><br/>
</template>
</div>
</div>
</form>
<button class="badge badge-danger mr-2"
@click="deleteAlbum"
>
Delete
</button>
<button type="submit" class="badge badge-success"
@click="updateAlbum"
>
Update
</button>
<p>{{ message }}</p>
</div>
<div v-else>
<br />
<p>Please click on a Album...</p>
</div>
</template>
<style>
.prokrutka {
height: 200px;
width: 100%;
background: #fff;
border: 1px solid #C1C1C1;
overflow-x: hidden;
overflow-y:scroll;
}
</style>
<script>
import AlbumDataService from '../services/AlbumDataService';
import ArtistDataService from '../services/ArtistDataService';
import SongDataService from '../services/SongDataService';
export default {
name: "album",
data() {
return {
currentAlbum: null,
artists : [],
songs : [],
message: ''
};
},
created() {
ArtistDataService.getAll()
.then(response => {
this.artists = response.data;
console.log(response.data);
});
SongDataService.getAll()
.then(response => {
this.songs = response.data;
console.log(response.data);
}
);
},
methods: {
getAlbum(id) {
AlbumDataService.get(id)
.then(response => {
this.currentAlbum = response.data;
console.log(response.data);
})
.artch(e => {
console.log(e);
});
},
updateAlbum() {
AlbumDataService.update(this.currentAlbum.id, this.currentAlbum)
.then(response => {
console.log(response.data);
this.message = 'The album was updated successfully!';
})
.artch(e => {
console.log(e);
});
},
deleteAlbum() {
AlbumDataService.delete(this.currentAlbum.id)
.then(response => {
console.log(response.data);
this.$router.push({ name: "albums" });
})
.artch(e => {
console.log(e);
});
}
},
mounted() {
this.message = '';
this.getAlbum(this.$route.params.id);
}
};
</script>
<style>
.edit-form {
max-width: 300px;
margin: auto;
}
</style>

View File

@ -0,0 +1,25 @@
import axios from "../http-common";
class AlbumDataService {
getAll() {
return axios.get( "/albums");
}
get(id) {
return axios.get( `/albums/${id}`);
}
create(data) {
return axios.post( `/albums`, data);
}
update(id, data) {
return axios.put(`/albums/${id}`, data);
}
delete(id) {
return axios.delete(`/albums/${id}`);
}
}
export default new AlbumDataService();

View File

@ -0,0 +1,25 @@
import axios from "../http-common";
class ArtistDataService {
getAll() {
return axios.get( "/artists");
}
get(id) {
return axios.get( `/artists/${id}`);
}
create(data) {
return axios.post( `/artists`, data);
}
update(id, data) {
return axios.put(`/artists/${id}`, data);
}
delete(id) {
return axios.delete(`/artists/${id}`);
}
}
export default new ArtistDataService();

View File

@ -0,0 +1,25 @@
import axios from "../http-common";
class SongDataService {
getAll() {
return axios.get( "/songs");
}
get(id) {
return axios.get( `/songs/${id}`);
}
create(data) {
return axios.post( `/songs`, data);
}
update(id, data) {
return axios.put(`/songs/${id}`, data);
}
delete(id) {
return axios.delete(`/songs/${id}`);
}
}
export default new SongDataService();

View File

@ -1,15 +1,50 @@
{
"name": "IP",
"version": "1.0.0",
"main": "index.html",
"name": "front",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "http-server -p 3001 ./",
"test": "echo \"Error: no test specified\" && exit 1"
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"bootstrap": "5.2.1"
"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": {
"http-server": "^14.1.1"
}
"@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"
]
}

25
front/react.js vendored
View File

@ -1,25 +0,0 @@
'use strict';
const e = React.createElement;
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = { liked: false };
}
render() {
if (this.state.liked) {
return 'You liked this.';
}
return e(
'button',
{ onClick: () => this.setState({ liked: true }) },
'Like'
);
}
}
const domContainer = document.querySelector('#like_button_container');
const root = ReactDOM.createRoot(domContainer);
root.render(e(LikeButton));

View File

@ -1,13 +0,0 @@
'use strict'
async function calculate(){
let num1 = document.getElementById("input1").value
let num2 = document.getElementById("input2").value
let operator = document.getElementById("operator").value
let result = document.getElementById("result")
let type = document.getElementById("Type").value
let response = await fetch(`http://localhost:8080/${operator}?Type=${type}&value1=${num1}&value2=${num2}`)
let res = await response.text()
result.value = res
}

View File

@ -1,43 +1,55 @@
package ru.ulstu.is.sbapp.controllers;
import org.springframework.validation.annotation.Validated;
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 java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/album")
public class AlbumController {
private final AlbumService albumService;
@Autowired
public AlbumController(AlbumService albumService){
this.albumService = albumService;
}
@PostMapping
public AlbumDTO addAlbum(@RequestBody @Validated AlbumDTO albumDTO){
return new AlbumDTO(albumService.addAlbum(albumDTO));
}
@PutMapping("/{id}")
public AlbumDTO updateAlbum(@PathVariable Long id, @RequestBody @Validated AlbumDTO albumDTO){
return new AlbumDTO(albumService.updateAlbum(id, albumDTO));
}
@DeleteMapping("/{id}")
public AlbumDTO removeAlbum(@PathVariable Long id){
return new AlbumDTO(albumService.deleteAlbum(id));
}
@DeleteMapping
public void removeAllAlbums(){
albumService.deleteAllAlbums();
}
@GetMapping("/{id}")
public AlbumDTO findAlbum(@PathVariable Long id){
@GetMapping("/albums/{id}")
public AlbumDTO getAlbum(@PathVariable Long id) {
return new AlbumDTO(albumService.findAlbum(id));
}
@GetMapping
public List<AlbumDTO> findAllAlbums(){
return albumService.findAllAlbums()
.stream()
.map(x -> new AlbumDTO(x))
.toList();
@GetMapping("/albums")
public List<AlbumDTO> getAlbums() {
return albumService.findAllAlbums().stream().map(AlbumDTO::new).toList();
}
@PostMapping("/albums")
public ResponseEntity<AlbumDTO> createAlbum(@RequestBody @Valid AlbumDTO albumDTO){
List<Long> list = new ArrayList<>();
for (ArtistDTO art:
albumDTO.getArtistList()) {
list.add(art.getId());
}
return new ResponseEntity<>
(new AlbumDTO(albumService.addAlbum
(albumDTO.getAlbumName(),list)), HttpStatus.OK);
}
@PutMapping("/albums/{id}")
public ResponseEntity<AlbumDTO> updateAlbum(@RequestBody @Valid AlbumDTO albumDTO){
List<Long> 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);
}
@DeleteMapping("/albums/{id}")
public AlbumDTO deleteAlbum(@PathVariable Long id){
return new AlbumDTO(albumService.deleteAlbum(id));
}
}

View File

@ -1,38 +1,41 @@
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 {
private long id;
private String albumName;
private List<SongDTO> songDTOList;
private List<ArtistDTO> artistDTOList;
@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<ArtistDTO> artistList;
public AlbumDTO(Album album){
this.id = album.getId();
this.albumName = album.getAlbumName();
this.artistDTOList = album.getArtists() == null ? null : album.getArtists()
.stream()
.filter(x -> x.getAlbum().contains(album))
.map(ArtistDTO::new)
.toList();
this.songDTOList = album.getSongs() == null ? null : album.getSongs()
.stream()
.map(SongDTO::new)
.toList();
this.artistList = album.getArtists().stream().map(ArtistDTO::new).toList();
}
public AlbumDTO(){}
public long getId() {
public AlbumDTO(Long id, String albumName, List<ArtistDTO> artistList){
this.id = id;
this.albumName = albumName;
this.artistList = artistList;
}
public Long getId() {
return id;
}
public String getAlbumName(){
return albumName;
}
public List<SongDTO> getSongDTOList(){
return songDTOList;
public List<ArtistDTO> getArtistList(){
return artistList;
}
public List<ArtistDTO> getArtistDTOList(){
return artistDTOList;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getData() {
return String.format("%s %s %s", id, albumName, artistList.toString());
}
}

View File

@ -1,6 +1,9 @@
package ru.ulstu.is.sbapp.controllers;
import org.springframework.validation.annotation.Validated;
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;
@ -10,45 +13,32 @@ import java.util.List;
@RequestMapping("/artist")
public class ArtistController {
private final ArtistService artistService;
@Autowired
public ArtistController(ArtistService artistService){
this.artistService = artistService;
}
@PostMapping
public ArtistDTO addArtist(@RequestBody @Validated ArtistDTO artistDTO) {
return new ArtistDTO(artistService.addArtist(artistDTO));
}
@PutMapping("/{id}")
public ArtistDTO updateArtist(@PathVariable Long id,@RequestBody @Validated ArtistDTO artistDTO) {
return new ArtistDTO(artistService.updateArtist(id, artistDTO));
}
@DeleteMapping("/{id}")
public ArtistDTO removeArtist(@PathVariable Long id) {
return new ArtistDTO(artistService.deleteArtist(id));
}
@DeleteMapping
public void removeAllArtists() {
artistService.deleteAllArtists();
}
@GetMapping("/{id}")
public ArtistDTO findArtist(@PathVariable Long id) {
@GetMapping("/artists/{id}")
public ArtistDTO getArtist(@PathVariable Long id) {
return new ArtistDTO(artistService.findArtist(id));
}
@GetMapping("/worker/{id}")
public List<SongDTO> findSongsOnWorkplace(@PathVariable Long id){
return artistService.findAllSongsProducedArtist(id)
.stream()
.map(SongDTO::new)
.toList();
}
@GetMapping
public List<ArtistDTO> findAllArtist() {
return artistService.findAllArtists()
.stream()
@GetMapping("/artists")
public List<ArtistDTO> getArtists() {
return artistService.findAllArtists().stream()
.map(ArtistDTO::new)
.toList();
}
@PostMapping("/artists")
public ResponseEntity<ArtistDTO> createArtist(@RequestBody @Valid ArtistDTO artistDTO) {
return new ResponseEntity<>(new ArtistDTO(artistService.addArtist(artistDTO.getArtistName(), artistDTO.getGenre())), HttpStatus.OK);
}
@PutMapping("/artists/{id}")
public ResponseEntity<ArtistDTO> updateArtist(@RequestBody @Valid ArtistDTO artistDTO) {
return new ResponseEntity<>(new ArtistDTO(artistService.updateArtist(artistDTO.getId(), artistDTO.getArtistName(), artistDTO.getGenre())), HttpStatus.OK);
}
@DeleteMapping("/artists/{id}")
public ArtistDTO deleteArtist(@PathVariable Long id) {
return new ArtistDTO(artistService.deleteArtist(id));
}
}

View File

@ -1,38 +1,35 @@
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 {
private long id;
private String artistName;
private String genre;
private List<AlbumDTO> albumDTOList;
@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;
public ArtistDTO(Artist artist){
this.id = artist.getId();
this.artistName = artist.getArtistName();
this.genre = artist.getGenre();
this.albumDTOList = artist.getAlbum() == null ? null : artist.getAlbum()
.stream()
.filter(x -> x.getArtists().contains(artist.getId()))
.map(y -> new AlbumDTO(y))
.toList();
}
public ArtistDTO() {
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() {
return artistName;
}
public String getGenre() {
return genre;
}
public List<AlbumDTO> getAlbumDTOList(){
return albumDTOList;
}
}

View File

@ -1,6 +1,9 @@
package ru.ulstu.is.sbapp.controllers;
import org.springframework.validation.annotation.Validated;
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.SongService;
@ -10,44 +13,34 @@ import java.util.List;
@RequestMapping("/song")
public class SongController {
private final SongService songService;
@Autowired
public SongController(SongService songService){
this.songService = songService;
}
@PostMapping
public SongDTO addSong(@RequestBody @Validated SongDTO songDTO) {
return new SongDTO(songService.addSong(songDTO));
}
@PutMapping("/{id}")
public SongDTO updateSong(@PathVariable Long id,@RequestBody @Validated SongDTO songDTO) {
return new SongDTO(songService.updateSong(id, songDTO));
}
@DeleteMapping("/{id}")
public SongDTO removeSong(@PathVariable Long id) {
return new SongDTO(songService.deleteSong(id));
}
@DeleteMapping
public void removeAllSongs() {
songService.deleteAllSongs();
}
@GetMapping("/{id}")
public SongDTO findSong(@PathVariable Long id) {
@GetMapping("/songs/{id}")
public SongDTO getSong(@PathVariable Long id) {
return new SongDTO(songService.findSong(id));
}
@GetMapping("/workplace/{id}")
public List<SongDTO> findSongsOnWorkplace(@PathVariable Long id){
return songService.findSongsInAlbum(id).stream()
@GetMapping("/songs")
public List<SongDTO> getSongs() {
return songService.findAllSongs().stream()
.map(SongDTO::new)
.toList();
}
@GetMapping
public List<SongDTO> findAllSong() {
return songService.findAllSongs()
.stream()
.map(x-> new SongDTO(x))
.toList();
@PostMapping("/songs")
public ResponseEntity<SongDTO> createSong(@RequestBody @Valid SongDTO songDTO) {
return new ResponseEntity<>
(new SongDTO(songService.addSong
(songDTO.getSongName(), songDTO.getDuration(), songDTO.getAlbum().getId())), HttpStatus.OK);
}
@PutMapping("/song/{id}")
public ResponseEntity<SongDTO> updateSong(@RequestBody @Valid SongDTO songDTO) {
return new ResponseEntity<>(new SongDTO(songService.updateSong(songDTO.getId(), songDTO.getSongName(), songDTO.getDuration(), songDTO.getAlbum().getId())), HttpStatus.OK);
}
@DeleteMapping("/songs/{id}")
public SongDTO deleteSong(@PathVariable Long id) {
return new SongDTO(songService.deleteSong(id));
}
}

View File

@ -1,17 +1,30 @@
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 {
private Long id;
private String songName;
private Double Duration;
@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){
this.id = song.getId();
this.songName = song.getSongName();
this.Duration = song.getSongDuration();
this.duration = song.getDuration();
this.album = new AlbumDTO(song.getAlbum());
}
public SongDTO(){
public SongDTO(Long id, String songName, Double duration, AlbumDTO album){
this.id = id;
this.songName = songName;
this.duration = duration;
this.album = album;
}
public Long getId() {
return id;
@ -19,7 +32,14 @@ public class SongDTO {
public String getSongName(){
return songName;
}
public Double getSongDuration(){
return Duration;
public Double getDuration(){
return duration;
}
public AlbumDTO getAlbum() {
return album;
}
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getData() {
return String.format("%s %s %s %s", id, songName, duration, album.getAlbumName());
}
}

View File

@ -1,96 +1,93 @@
package ru.ulstu.is.sbapp.database.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Entity
@Table(name = "album")
public class Album {
@Id
@GeneratedValue
private long id;
@NotNull(message = "Name can't be empty")
@Column(name = "name")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotBlank
private String albumName;
@OneToMany(cascade = {CascadeType.MERGE})
@JoinColumn(name = "songs", nullable = true)
@OneToMany(fetch = FetchType.EAGER,mappedBy = "album")
private List<Song> songs;
@ManyToMany(cascade = { CascadeType.MERGE }, fetch = FetchType.EAGER)
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "albums_artists",
joinColumns = @JoinColumn(name = "album_fk"),
inverseJoinColumns = @JoinColumn(name = "artist_fk"))
private List<Artist> artists;
public Album(){
}
public Album(String albumName, List<Artist> artists, List<Song> songs){
public Album(){}
public Album(String albumName){
this.albumName = albumName;
this.artists = artists;
this.songs = songs;
}
public Long getId() {
return id;
}
public String getAlbumName() {
public String getAlbumName(){
return albumName;
}
public void setAlbumName(String albumName) {
this.albumName = albumName;
}
public List<Artist> getArtists() {
public List<Artist> getArtists(){
return artists;
}
public List<Song> getSongs(){return songs;}
public void setArtists(List<Artist> artists) {
this.artists = artists;
}
public void setSongs(List<Song> songs) {
this.songs = songs;
}
public void update(Album album){
this.albumName = album.albumName;
this.artists = album.getArtists();
}
public void addArtist(Artist artist){
if (artists == null){
this.artists = new ArrayList<>();
}
if (!artists.contains(artist)) {
this.artists.add(artist);
artist.addAlbum(this);
}
if(artists==null)
artists=new ArrayList<>();
artists.add(artist);
artist.addAlbum(this);
}
public void setArtists(List<Artist> art){
this.artists=art;
}
public void removeArtist(Artist artist){
if (artists.contains(artist)) {
this.artists.remove(artist);
if(artists!=null){
artists.remove(artist);
artist.removeAlbum(this);
}
}
public void addSong(Song song){
if (songs == null){
this.songs = new ArrayList<>();
}
if (!songs.contains(song)) {
this.songs.add(song);
}
public List<Song> getSongs(){
return songs;
}
public void removeSong(Song song){
if (songs.contains(song)) {
this.songs.remove(song);
}
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);
}
@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);
@ -100,7 +97,8 @@ public class Album {
public String toString() {
return "Album{" +
"id=" + id +
", albumName='" + albumName + '\'' +
", Name='" + albumName + '\'' +
"Artists:" + (artists == null ? "[]" : artists.toString()) +
'}';
}
}

View File

@ -1,7 +1,7 @@
package ru.ulstu.is.sbapp.database.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;
@ -10,73 +10,57 @@ import java.util.Objects;
@Entity
public class Artist {
@Id
@GeneratedValue
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull(message = "Name can't be empty")
@Column(name = "artistName")
@NotBlank
private String artistName;
@NotNull(message = "Genre can't be null or empty")
@Column(name = "genre")
@NotBlank
private String genre;
@ManyToMany(mappedBy = "artists",cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
private List<Album> album;
public Artist() {
}
@ManyToMany(fetch = FetchType.EAGER,mappedBy = "artists")
private List<Album> albums;
public Artist(String artistName, String genre) {
public Artist(){}
public Artist(String artistName, String genre){
this.artistName = artistName;
this.genre = genre;
}
public Long getId() {
return id;
}
public String getArtistName() {
public String getArtistName(){
return artistName;
}
public void setArtistName(String artistName) {
this.artistName = artistName;
public void setArtistName(String value){
artistName=value;
}
public String getGenre() {
public String getGenre(){
return genre;
}
public void setGenre(String genre) {
this.genre = genre;
public void setGenre(String value){
genre=value;
}
public List<Album> getAlbum() {
return album;
public List<Album> getAlbums(){
return albums;
}
public void setAlbum(List<Album> album) {
this.album = album;
public void addAlbum(Album album){
if(albums==null)
albums = new ArrayList<>();
albums.add(album);
}
public void addAlbum(Album album) {
if (this.album == null) {
this.album = new ArrayList<>();
}
if (!this.album.contains(album))
this.album.add(album);
public void removeAlbum(Album album){
if(album!=null)
albums.remove(album);
}
public void removeAlbum(Album album) {
if (this.album.contains(album))
this.album.remove(album);
}
@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);
@ -86,8 +70,8 @@ public class Artist {
public String toString() {
return "Artist{" +
"id=" + id +
", artistName='" + artistName + '\'' +
", genre='" + genre + '\'' +
", Name='" + artistName + '\'' +
", Genre='" + genre + '\'' +
'}';
}
}

View File

@ -1,6 +1,7 @@
package ru.ulstu.is.sbapp.database.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.Objects;
@ -9,39 +10,50 @@ import java.util.Objects;
@Table(name = "song")
public class Song {
@Id
@GeneratedValue
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull(message = "Name can't be empty")
@Column(name = "name")
@NotBlank
private String songName;
@NotNull(message = "Duration can't be empty")
@Column(name = "duration")
private Double Duration;
public Song(){
@NotBlank
private Double duration;
@NotNull
@ManyToOne
private Album album;
public Song(){}
public Song(String songName, Double duration){
this.songName=songName;
this.duration=duration;
}
public Song(String songName, Double Duration){
this.songName = songName;
this.Duration = Duration;
public Long getId() {
return id;
}
public Long getId(){return id;}
public String getSongName(){
return songName;
}
public Double getSongDuration(){
return Duration;
}
public void setSongName(String songName) {
this.songName = songName;
}
public void setSongDuration(Double Duration) {
this.Duration = Duration;
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);
}
@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
@ -54,7 +66,7 @@ public class Song {
return "Song{" +
"id=" + id +
", songName='" + songName + '\'' +
", Duration='" + Duration + '\'' +
", Duration='" + duration + '\'' +
'}';
}
}

View File

@ -3,51 +3,45 @@ package ru.ulstu.is.sbapp.database.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.is.sbapp.Repository.IAlbumRepository;
import ru.ulstu.is.sbapp.controllers.AlbumDTO;
import ru.ulstu.is.sbapp.database.model.Album;
import ru.ulstu.is.sbapp.database.model.Artist;
import ru.ulstu.is.sbapp.database.model.Song;
import ru.ulstu.is.sbapp.database.util.validation.ValidatorUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Service
public class AlbumService {
private final IAlbumRepository albumRepository;
private final ArtistService artistService;
private final SongService songService;
public AlbumService(IAlbumRepository albumRepository,
ArtistService artistService,
SongService songService
){
private final ValidatorUtil validatorUtil;
private final ArtistService artistService;
public AlbumService(IAlbumRepository albumRepository, ValidatorUtil validatorUtil, ArtistService artistService){
this.albumRepository = albumRepository;
this.validatorUtil = validatorUtil;
this.artistService = artistService;
this.songService = songService;
}
@Transactional
public Album addAlbum(AlbumDTO albumDTO) {
public Album addAlbum(String albumName, List<Long> artistsId) {
final Album album = new Album(albumName);
if(artistsId.size() > 0 )
{
for (Long id:
artistsId) {
Artist art = artistService.findArtist(id);
album.addArtist(art);
}
}
else
album.setArtists(new ArrayList<>());
validatorUtil.validate(album);
List<Artist> artists = artistService.findAllArtistsById(albumDTO);
List<Song> songs = songService.findAllSongById(albumDTO);
return albumRepository.save(album);
}
final Album album = new Album(
albumDTO.getAlbumName(), artists, songs);
albumRepository.save(album);
return album;
}
@Transactional
public Album addSong(AlbumDTO albumDTO, List<Song> songs){
final Album currentAlbum = findAlbum(albumDTO.getId());
currentAlbum.setSongs(songs);
return currentAlbum;
}
@Transactional
public Album addArtist(AlbumDTO albumDTO, List<Artist> artists){
final Album currentAlbum = findAlbum(albumDTO.getId());
currentAlbum.setArtists(artists);
return currentAlbum;
}
@Transactional(readOnly = true)
public Album findAlbum(Long id) {
final Optional<Album> album = albumRepository.findById(id);
@ -59,24 +53,31 @@ public class AlbumService {
}
@Transactional
public Album updateAlbum(Long id, AlbumDTO albumDTO) {
public Album updateAlbum(Long id, String albumName, List<Long> artistIds) {
final Album currentAlbum = findAlbum(id);
currentAlbum.setAlbumName(albumDTO.getAlbumName());
List<Artist> newArtists = artistService.findAllArtistsById(albumDTO);
List<Song> newSongs = songService.findAllSongById(albumDTO);
currentAlbum.setArtists(newArtists);
currentAlbum.setSongs(newSongs);
albumRepository.save(currentAlbum);
return currentAlbum;
currentAlbum.setAlbumName(albumName);
if(artistIds.size()>0)
{
currentAlbum.getArtists().clear();
for (Long ArtId:
artistIds) {
Artist art = artistService.findArtist(ArtId);
currentAlbum.addArtist(art);
}
}
else
currentAlbum.getArtists().clear();
validatorUtil.validate(currentAlbum);
return albumRepository.save(currentAlbum);
}
@Transactional
public Album deleteAlbum(Long id) {
final Album currentAlbum = findAlbum(id);
albumRepository.delete(currentAlbum);
return currentAlbum;
}
@Transactional
public void deleteAllAlbums() {
albumRepository.deleteAll();

View File

@ -3,72 +3,57 @@ package ru.ulstu.is.sbapp.database.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.is.sbapp.Repository.IArtistRepository;
import ru.ulstu.is.sbapp.controllers.AlbumDTO;
import ru.ulstu.is.sbapp.controllers.ArtistDTO;
import ru.ulstu.is.sbapp.database.model.Album;
import ru.ulstu.is.sbapp.database.model.Artist;
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;
@Service
public class ArtistService {
private final IArtistRepository artistRepository;
public ArtistService(IArtistRepository artistRepository){
private final ValidatorUtil validatorUtil;
public ArtistService(IArtistRepository artistRepository,
ValidatorUtil validatorUtil) {
this.artistRepository = artistRepository;
this.validatorUtil = validatorUtil;
}
@Transactional
public Artist addArtist(ArtistDTO artistDTO) {
Artist artist =new Artist(artistDTO.getArtistName(), artistDTO.getGenre());
artistRepository.save(artist);
return artist;
public Artist addArtist(String artistName, String genre) {
final Artist artist = new Artist(artistName, genre);
validatorUtil.validate(artist);
return artistRepository.save(artist);
}
@Transactional(readOnly = true)
public Artist findArtist(Long id) {
final Optional<Artist> artist = artistRepository.findById(id);
return artist.orElseThrow(()->new ArtistNotFoundException(id));
return artist.orElseThrow(() -> new ArtistNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Artist> findAllArtists() {
return artistRepository.findAll();
}
@Transactional(readOnly = true)
public List<Artist> findAllArtistsById(AlbumDTO albumDTO) {
return artistRepository
.findAllById(albumDTO
.getArtistDTOList()
.stream()
.map(x -> x.getId())
.toList());
}
@Transactional
public Artist updateArtist(Long id, ArtistDTO artistDTO) {
public Artist updateArtist(Long id, String artistName, String genre) {
final Artist currentArtist = findArtist(id);
currentArtist.setArtistName(artistDTO.getArtistName());
currentArtist.setGenre(artistDTO.getGenre());
artistRepository.save(currentArtist);
return currentArtist;
currentArtist.setArtistName(artistName);
currentArtist.setGenre(genre);
validatorUtil.validate(currentArtist);
return artistRepository.save(currentArtist);
}
@Transactional
public Artist deleteArtist(Long id) {
final Artist currentArtist= findArtist(id);
int size = currentArtist.getAlbum().size();
for (int i = 0; i < size; i++) {
Album temp = currentArtist.getAlbum().get(i);
temp.removeArtist(currentArtist);
currentArtist.removeAlbum(temp);
}
final Artist currentArtist = findArtist(id);
artistRepository.delete(currentArtist);
return currentArtist;
}
@Transactional
public List<Song> findAllSongsProducedArtist(Long id){
return artistRepository.getSongs(findArtist(id));
}
@Transactional
public void deleteAllArtists() {
artistRepository.deleteAll();

View File

@ -3,53 +3,55 @@ package ru.ulstu.is.sbapp.database.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.is.sbapp.Repository.ISongRepository;
import ru.ulstu.is.sbapp.controllers.SongDTO;
import ru.ulstu.is.sbapp.controllers.AlbumDTO;
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;
@Service
public class SongService {
private final ISongRepository songRepository;
public SongService(ISongRepository songRepository){
private final ValidatorUtil validatorUtil;
private final AlbumService albumService;
public SongService(ISongRepository songRepository, ValidatorUtil validatorUtil, AlbumService albumService){
this.songRepository = songRepository;
this.validatorUtil = validatorUtil;
this.albumService = albumService;
}
@Transactional
public Song addSong(SongDTO songDTO) {
final Song song = new Song(songDTO.getSongName(), songDTO.getSongDuration());
songRepository.save(song);
return song;
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);
return songRepository.save(song);
}
@Transactional(readOnly = true)
public Song findSong(Long id) {
final Optional<Song> song = songRepository.findById(id);
return song.orElseThrow(()->new SongNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Song> findAllSongById(AlbumDTO albumDTO) {
return songRepository
.findAllById(albumDTO
.getSongDTOList()
.stream()
.map(x->x.getId())
.toList());
return song.orElseThrow(() -> new SongNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Song> findAllSongs() {
return songRepository
.findAll();
return songRepository.findAll();
}
@Transactional
public Song updateSong(Long id, SongDTO song) {
public Song updateSong(Long id, String songName, Double duration, Long albumId) {
final Song currentSong = findSong(id);
currentSong.setSongName(song.getSongName());
currentSong.setSongDuration(song.getSongDuration());
songRepository.save(currentSong);
return currentSong;
currentSong.setSongName(songName);
currentSong.setDuration(duration);
Album curAlbum = albumService.findAlbum(albumId);
currentSong.setAlbum(curAlbum);
validatorUtil.validate(currentSong);
return songRepository.save(currentSong);
}
@Transactional
@ -59,11 +61,6 @@ public class SongService {
return currentSong;
}
@Transactional
public List<Song> findSongsInAlbum(Long id){
return songRepository.findSongsInAlbum(findSong(id));
}
@Transactional
public void deleteAllSongs() {
songRepository.deleteAll();

View File

@ -0,0 +1,42 @@
package ru.ulstu.is.sbapp.database.util.error;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import ru.ulstu.is.sbapp.database.service.AlbumNotFoundException;
import ru.ulstu.is.sbapp.database.service.ArtistNotFoundException;
import ru.ulstu.is.sbapp.database.service.SongNotFoundException;
import ru.ulstu.is.sbapp.database.util.validation.ValidationException;
import java.util.stream.Collectors;
@ControllerAdvice
public class AdviceController {
@ExceptionHandler({
AlbumNotFoundException.class,
ArtistNotFoundException.class,
SongNotFoundException.class,
ValidationException.class
})
public ResponseEntity<Object> handleException(Throwable e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleBindException(MethodArgumentNotValidException e) {
final ValidationException validationException = new ValidationException(
e.getBindingResult().getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toSet()));
return handleException(validationException);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleUnknownException(Throwable e) {
e.printStackTrace();
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}

View File

@ -0,0 +1,9 @@
package ru.ulstu.is.sbapp.database.util.validation;
import java.util.Set;
public class ValidationException extends RuntimeException {
public ValidationException(Set<String> errors) {
super(String.join("\n", errors));
}
}

View File

@ -0,0 +1,30 @@
package ru.ulstu.is.sbapp.database.util.validation;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.springframework.stereotype.Component;
import java.util.Set;
import java.util.stream.Collectors;
@Component
public class ValidatorUtil {
private final Validator validator;
public ValidatorUtil() {
try (ValidatorFactory factory = Validation.buildDefaultValidatorFactory()) {
this.validator = factory.getValidator();
}
}
public <T> void validate(T object) {
final Set<ConstraintViolation<T>> errors = validator.validate(object);
if (!errors.isEmpty()) {
throw new ValidationException(errors.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toSet()));
}
}
}