diff --git a/src/main/java/com/mediamanager/mapper/AlbumHasGenreMapper.java b/src/main/java/com/mediamanager/mapper/AlbumHasGenreMapper.java new file mode 100644 index 0000000..43c34f3 --- /dev/null +++ b/src/main/java/com/mediamanager/mapper/AlbumHasGenreMapper.java @@ -0,0 +1,47 @@ +package com.mediamanager.mapper; + +import com.mediamanager.model.AlbumHasGenre; +import com.mediamanager.protocol.messages.AlbumHasGenreMessages; + +public class AlbumHasGenreMapper { + public static AlbumHasGenreMessages.AlbumHasGenre toProtobuf(AlbumHasGenre entity) { + if (entity == null) { + return null; + } + + AlbumHasGenreMessages.AlbumHasGenre.Builder builder = AlbumHasGenreMessages.AlbumHasGenre.newBuilder(); + + Integer id = entity.getId(); + if (id != null) { + builder.setId(id); + } + + // Map Album foreign key + if (entity.getAlbum() != null && entity.getAlbum().getId() != null) { + builder.setFkAlbumId(entity.getAlbum().getId()); + } + + // Map Genre foreign key + if (entity.getGenre() != null && entity.getGenre().getId() != null) { + builder.setFkGenreId(entity.getGenre().getId()); + } + + return builder.build(); + } + + public static AlbumHasGenre toEntity(AlbumHasGenreMessages.AlbumHasGenre protobuf) { + if (protobuf == null) { + return null; + } + + AlbumHasGenre entity = new AlbumHasGenre(); + + if (protobuf.getId() > 0) { + entity.setId(protobuf.getId()); + } + + // Note: Foreign key relationships (Album, Genre) are handled in the service layer + + return entity; + } +} diff --git a/src/main/java/com/mediamanager/model/AlbumHasGenre.java b/src/main/java/com/mediamanager/model/AlbumHasGenre.java new file mode 100644 index 0000000..c380a89 --- /dev/null +++ b/src/main/java/com/mediamanager/model/AlbumHasGenre.java @@ -0,0 +1,56 @@ +package com.mediamanager.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "albumshasgenre") +public class AlbumHasGenre { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "fk_album_id", nullable = false) + private Album album; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "fk_genre_id", nullable = false) + private Genre genre; + + public AlbumHasGenre() {} + + // Getters and Setters + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Album getAlbum() { + return album; + } + + public void setAlbum(Album album) { + this.album = album; + } + + public Genre getGenre() { + return genre; + } + + public void setGenre(Genre genre) { + this.genre = genre; + } + + @Override + public String toString() { + return "AlbumHasGenre{" + + "id=" + id + + ", albumId=" + (album != null ? album.getId() : null) + + ", genreId=" + (genre != null ? genre.getId() : null) + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/com/mediamanager/repository/AlbumHasGenreRepository.java b/src/main/java/com/mediamanager/repository/AlbumHasGenreRepository.java new file mode 100644 index 0000000..d842224 --- /dev/null +++ b/src/main/java/com/mediamanager/repository/AlbumHasGenreRepository.java @@ -0,0 +1,85 @@ +package com.mediamanager.repository; + + +import com.mediamanager.model.AlbumHasGenre; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + + +import java.util.List; +import java.util.Optional; + +public class AlbumHasGenreRepository { + private static final Logger logger = LogManager.getLogger(AlbumHasGenreRepository.class); + + private final EntityManagerFactory entityManagerFactory; + + public AlbumHasGenreRepository(EntityManagerFactory entityManagerFactory) { + this.entityManagerFactory = entityManagerFactory; + } + + public AlbumHasGenre save(AlbumHasGenre albumHasGenre) { + logger.debug("Saving AlbumHasGenre: {}", albumHasGenre); + EntityManager em = entityManagerFactory.createEntityManager(); + em.getTransaction().begin(); + try { + em.persist(albumHasGenre); + em.getTransaction().commit(); + logger.debug("AlbumHasGenre has been saved successfully"); + return albumHasGenre; + } catch (Exception e) { + em.getTransaction().rollback(); + logger.error("Error while saving AlbumHasGenre: {}", e.getMessage()); + throw e; + } finally { + if (em.isOpen()) em.close(); + } + } + + public List findAll() { + logger.debug("Finding All AlbumHasGenre"); + EntityManager em = entityManagerFactory.createEntityManager(); + try{ + return em.createQuery("select a from AlbumHasGenre a", AlbumHasGenre.class).getResultList(); + }finally { + if (em.isOpen()) em.close(); + } + } + + public Optional findById(Integer id) { + logger.debug("Finding AlbumHasGenre with id: {}", id); + EntityManager em = entityManagerFactory.createEntityManager(); + try{ + AlbumHasGenre albumHasGenre = em.find(AlbumHasGenre.class, id); + return Optional.ofNullable(albumHasGenre); + }finally { + if (em.isOpen()) em.close(); + } + } + + public boolean deleteById(Integer id){ + logger.debug("Deleting AlbumHasGenre with id: {}", id); + EntityManager em = entityManagerFactory.createEntityManager(); + em.getTransaction().begin(); + try{ + AlbumHasGenre albumHasGenre = em.find(AlbumHasGenre.class, id); + if (albumHasGenre == null) { + em.getTransaction().rollback(); + return false; + } + em.remove(albumHasGenre); + em.getTransaction().commit(); + logger.debug("AlbumHasGenre has been deleted successfully"); + return true; + } catch (Exception e) { + em.getTransaction().rollback(); + logger.error("Error while deleting AlbumHasGenre: {}", e.getMessage()); + throw e; + } finally { + if (em.isOpen()) em.close(); + } + } + +} diff --git a/src/main/java/com/mediamanager/service/albumhasgenre/AlbumHasGenreService.java b/src/main/java/com/mediamanager/service/albumhasgenre/AlbumHasGenreService.java new file mode 100644 index 0000000..d75c5e8 --- /dev/null +++ b/src/main/java/com/mediamanager/service/albumhasgenre/AlbumHasGenreService.java @@ -0,0 +1,77 @@ +package com.mediamanager.service.albumhasgenre; + +import com.mediamanager.model.Album; +import com.mediamanager.model.AlbumHasGenre; +import com.mediamanager.model.Genre; +import com.mediamanager.repository.AlbumHasGenreRepository; +import com.mediamanager.repository.AlbumRepository; +import com.mediamanager.repository.GenreRepository; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.List; +import java.util.Optional; + +public class AlbumHasGenreService { + private static final Logger logger = LogManager.getLogger(AlbumHasGenreService.class); + private final AlbumHasGenreRepository repository; + private final AlbumRepository albumRepository; + private final GenreRepository genreRepository; + + public AlbumHasGenreService(AlbumHasGenreRepository repository, AlbumRepository albumRepository, GenreRepository genreRepository) { + this.repository = repository; + this.albumRepository = albumRepository; + this.genreRepository = genreRepository; + } + + public AlbumHasGenre createAlbumHasGenre(Integer albumId, Integer genreId) { + logger.debug("Creating album has genre relationship - albumId:{}, genreId:{}", albumId, genreId); + + if (albumId == null || albumId <= 0) { + throw new IllegalArgumentException("Album ID cannot be null or invalid"); + } + if (genreId == null || genreId <= 0) { + throw new IllegalArgumentException("Genre ID cannot be null or invalid"); + } + + // Verify Album exists + Optional album = albumRepository.findById(albumId); + if (album.isEmpty()) { + throw new IllegalArgumentException("Album not found with id: " + albumId); + } + + // Verify Genre exists + Optional genre = genreRepository.findById(genreId); + if (genre.isEmpty()) { + throw new IllegalArgumentException("Genre not found with id: " + genreId); + } + + AlbumHasGenre albumHasGenre = new AlbumHasGenre(); + albumHasGenre.setAlbum(album.get()); + albumHasGenre.setGenre(genre.get()); + + return repository.save(albumHasGenre); + } + + public List getAllAlbumHasGenres() { + logger.info("Getting all album has genre relationships"); + return repository.findAll(); + } + + public Optional getAlbumHasGenreById(Integer id) { + if (id == null) { + throw new IllegalArgumentException("ID cannot be null"); + } + logger.info("Getting album has genre by id:{}", id); + return repository.findById(id); + } + + public boolean deleteAlbumHasGenre(Integer id) { + if (id == null) { + throw new IllegalArgumentException("Album has genre id cannot be null"); + } + logger.info("Deleting album has genre:{}", id); + return repository.deleteById(id); + } + +} diff --git a/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java b/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java index 8fca373..1f1cb81 100644 --- a/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java +++ b/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java @@ -6,6 +6,7 @@ import com.mediamanager.repository.*; import com.mediamanager.service.album.AlbumService; import com.mediamanager.service.albumart.AlbumArtService; import com.mediamanager.service.albumhasartist.AlbumHasArtistService; +import com.mediamanager.service.albumhasgenre.AlbumHasGenreService; import com.mediamanager.service.albumtype.AlbumTypeService; import com.mediamanager.service.bitdepth.BitDepthService; import com.mediamanager.service.bitrate.BitRateService; @@ -95,6 +96,10 @@ public class DelegateActionManager { AlbumHasArtistService albumHasArtistService = new AlbumHasArtistService(albumHasArtistRepository, albumRepository, artistRepository); serviceLocator.register(AlbumHasArtistService.class, albumHasArtistService); + AlbumHasGenreRepository albumHasGenreRepository = new AlbumHasGenreRepository(entityManagerFactory); + AlbumHasGenreService albumHasGenreService = new AlbumHasGenreService(albumHasGenreRepository, albumRepository, genreRepository); + serviceLocator.register(AlbumHasGenreService.class, albumHasGenreService); + serviceLocator.logRegisteredServices(); logger.info("Services initialized successfully"); diff --git a/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/CreateAlbumHasGenreHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/CreateAlbumHasGenreHandler.java new file mode 100644 index 0000000..4577a46 --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/CreateAlbumHasGenreHandler.java @@ -0,0 +1,54 @@ +package com.mediamanager.service.delegate.handler.albumhasgenre; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.AlbumHasGenreMapper; +import com.mediamanager.model.AlbumHasGenre; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.AlbumHasGenreMessages; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.albumhasgenre.AlbumHasGenreService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Action("albumhasgenre.create") +public class CreateAlbumHasGenreHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(CreateAlbumHasGenreHandler.class); + private final AlbumHasGenreService albumHasGenreService; + + public CreateAlbumHasGenreHandler(AlbumHasGenreService albumHasGenreService) { + this.albumHasGenreService = albumHasGenreService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException { + try{ + AlbumHasGenreMessages.CreateAlbumHasGenreRequest createRequest = + AlbumHasGenreMessages.CreateAlbumHasGenreRequest.parseFrom(requestPayload); + + AlbumHasGenre albumHasGenre = albumHasGenreService.createAlbumHasGenre( + createRequest.getFkAlbumId() > 0 ? createRequest.getFkAlbumId() : null, + createRequest.getFkGenreId() > 0 ? createRequest.getFkGenreId() : null + ); + + AlbumHasGenreMessages.AlbumHasGenre albumHasGenreProto = AlbumHasGenreMapper.toProtobuf(albumHasGenre); + AlbumHasGenreMessages.CreateAlbumHasGenreResponse createAlbumHasGenreResponse = AlbumHasGenreMessages.CreateAlbumHasGenreResponse.newBuilder() + .setAlbumhasgenre(albumHasGenreProto) + .build(); + return TransportProtocol.Response.newBuilder() + .setPayload(createAlbumHasGenreResponse.toByteString()); + } catch (IllegalArgumentException e) { + logger.error("Validation error", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(400) + .setPayload(ByteString.copyFromUtf8("Validation error: " + e.getMessage())); + + } catch (Exception e) { + logger.error("Error creating album has genre", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage())); + } + } +} diff --git a/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/DeleteAlbumHasGenreHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/DeleteAlbumHasGenreHandler.java new file mode 100644 index 0000000..149cc4c --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/DeleteAlbumHasGenreHandler.java @@ -0,0 +1,62 @@ +package com.mediamanager.service.delegate.handler.albumhasgenre; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.AlbumHasGenreMessages; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.albumhasgenre.AlbumHasGenreService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Action("albumhasgenre.delete") +public class DeleteAlbumHasGenreHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(DeleteAlbumHasGenreHandler.class); + + private final AlbumHasGenreService albumHasGenreService; + + public DeleteAlbumHasGenreHandler(AlbumHasGenreService albumHasGenreService) { + this.albumHasGenreService = albumHasGenreService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) + throws InvalidProtocolBufferException { + + try { + AlbumHasGenreMessages.DeleteAlbumHasGenreRequest deleteRequest = + AlbumHasGenreMessages.DeleteAlbumHasGenreRequest.parseFrom(requestPayload); + int id = deleteRequest.getId(); + boolean success = albumHasGenreService.deleteAlbumHasGenre(id); + AlbumHasGenreMessages.DeleteAlbumHasGenreResponse deleteResponse; + if (success) { + deleteResponse = AlbumHasGenreMessages.DeleteAlbumHasGenreResponse.newBuilder() + .setSuccess(true) + .setMessage("Album has genre deleted successfully") + .build(); + return TransportProtocol.Response.newBuilder() + .setPayload(deleteResponse.toByteString()); + } else { + deleteResponse = AlbumHasGenreMessages.DeleteAlbumHasGenreResponse.newBuilder() + .setSuccess(false) + .setMessage("Album has genre not found") + .build(); + + return TransportProtocol.Response.newBuilder() + .setStatusCode(404) + .setPayload(deleteResponse.toByteString()); + } + } catch (Exception e) { + logger.error("Error deleting album has genre", e); + AlbumHasGenreMessages.DeleteAlbumHasGenreResponse deleteResponse = + AlbumHasGenreMessages.DeleteAlbumHasGenreResponse.newBuilder() + .setSuccess(false) + .setMessage("Error: " + e.getMessage()) + .build(); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(deleteResponse.toByteString()); + } + } + } diff --git a/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/GetAlbumHasGenreByIdHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/GetAlbumHasGenreByIdHandler.java new file mode 100644 index 0000000..a6835c0 --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/GetAlbumHasGenreByIdHandler.java @@ -0,0 +1,56 @@ +package com.mediamanager.service.delegate.handler.albumhasgenre; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.AlbumHasGenreMapper; +import com.mediamanager.model.AlbumHasGenre; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.AlbumHasGenreMessages; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.albumhasgenre.AlbumHasGenreService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Optional; + +@Action(value = "albumhasgenre.getById") +public class GetAlbumHasGenreByIdHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(GetAlbumHasGenreByIdHandler.class); + private final AlbumHasGenreService albumHasGenreService; + + public GetAlbumHasGenreByIdHandler(AlbumHasGenreService albumHasGenreService) { + this.albumHasGenreService = albumHasGenreService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) + throws InvalidProtocolBufferException{ + + try{ + AlbumHasGenreMessages.GetAlbumHasGenreByIdRequest getByIdRequest = + AlbumHasGenreMessages.GetAlbumHasGenreByIdRequest.parseFrom(requestPayload); + int id = getByIdRequest.getId(); + + Optional albumHasGenreOpt = albumHasGenreService.getAlbumHasGenreById(id); + + if (albumHasGenreOpt.isEmpty()){ + logger.warn("AlbumHasGenre not found with ID: {}", id); + return TransportProtocol.Response.newBuilder() + .setStatusCode(404) + .setPayload(ByteString.copyFromUtf8("AlbumHasGenre not found")); + } + AlbumHasGenreMessages.AlbumHasGenre albumHasGenreProto = AlbumHasGenreMapper.toProtobuf(albumHasGenreOpt.get()); + AlbumHasGenreMessages.GetAlbumHasGenreByIdResponse getByIdResponse = AlbumHasGenreMessages.GetAlbumHasGenreByIdResponse.newBuilder() + .setAlbumhasgenre(albumHasGenreProto) + .build(); + return TransportProtocol.Response.newBuilder() + .setPayload(getByIdResponse.toByteString()); + } catch (Exception e) { + logger.error("Error getting album has genre by ID", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(ByteString.copyFromUtf8("Error: "+ e.getMessage())); + } + } +} diff --git a/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/GetAlbumHasGenreHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/GetAlbumHasGenreHandler.java new file mode 100644 index 0000000..d90dcc1 --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/albumhasgenre/GetAlbumHasGenreHandler.java @@ -0,0 +1,48 @@ +package com.mediamanager.service.delegate.handler.albumhasgenre; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.AlbumHasGenreMapper; +import com.mediamanager.model.AlbumHasGenre; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.AlbumHasGenreMessages; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.albumhasgenre.AlbumHasGenreService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.List; + + +@Action("albumhasgenre.getAll") +public class GetAlbumHasGenreHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(GetAlbumHasGenreHandler.class); + + private final AlbumHasGenreService albumHasGenreService; + + public GetAlbumHasGenreHandler(AlbumHasGenreService albumHasGenreService){this.albumHasGenreService = albumHasGenreService;} + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException { + try{ + List albumHasGenres = albumHasGenreService.getAllAlbumHasGenres(); + AlbumHasGenreMessages.GetAlbumHasGenresResponse.Builder responseBuilder = AlbumHasGenreMessages.GetAlbumHasGenresResponse.newBuilder(); + + for (AlbumHasGenre albumHasGenre : albumHasGenres) { + AlbumHasGenreMessages.AlbumHasGenre albumHasGenreProto = AlbumHasGenreMapper.toProtobuf(albumHasGenre); + responseBuilder.addAlbumhasgenre(albumHasGenreProto); + } + AlbumHasGenreMessages.GetAlbumHasGenresResponse getAlbumHasGenresResponse = responseBuilder.build(); + + return TransportProtocol.Response.newBuilder() + .setPayload(getAlbumHasGenresResponse.toByteString()); + + }catch (Exception e){ + logger.error("Error getting album has genres", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage())); + } + } +} diff --git a/src/main/proto/albumhasgenre.proto b/src/main/proto/albumhasgenre.proto new file mode 100644 index 0000000..441de1d --- /dev/null +++ b/src/main/proto/albumhasgenre.proto @@ -0,0 +1,46 @@ +syntax = "proto3"; + +option java_package = "com.mediamanager.protocol.messages"; +option java_outer_classname = "AlbumHasGenreMessages"; + +package mediamanager.messages; + +message AlbumHasGenre { + int32 id = 1; + int32 fk_album_id = 2; + int32 fk_genre_id = 3; +} + +message CreateAlbumHasGenreRequest { + int32 fk_album_id = 1; + int32 fk_genre_id = 2; +} + +message CreateAlbumHasGenreResponse { + AlbumHasGenre albumhasgenre = 1; +} + +message GetAlbumHasGenresRequest { + +} + +message GetAlbumHasGenresResponse { + repeated AlbumHasGenre albumhasgenre = 1; +} + +message GetAlbumHasGenreByIdRequest { + int32 id = 1; +} + +message GetAlbumHasGenreByIdResponse { + AlbumHasGenre albumhasgenre = 1; +} + +message DeleteAlbumHasGenreRequest { + int32 id = 1; +} + +message DeleteAlbumHasGenreResponse { + bool success = 1; + string message = 2; +} \ No newline at end of file