diff --git a/src/main/java/com/mediamanager/mapper/DiscMapper.java b/src/main/java/com/mediamanager/mapper/DiscMapper.java new file mode 100644 index 0000000..6ee867f --- /dev/null +++ b/src/main/java/com/mediamanager/mapper/DiscMapper.java @@ -0,0 +1,50 @@ +package com.mediamanager.mapper; + +import com.mediamanager.model.Disc; +import com.mediamanager.protocol.messages.DiscMessages; + +public class DiscMapper { + public static DiscMessages.Disc toProtobuf(Disc entity) { + if (entity == null) { + return null; + } + + Integer discNumber = entity.getDiscNumber(); + if (discNumber == null) { + throw new IllegalArgumentException("Disc number cannot be null"); + } + + DiscMessages.Disc.Builder builder = DiscMessages.Disc.newBuilder() + .setDiscNumber(discNumber); + + 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()); + } + + return builder.build(); + } + + public static Disc toEntity(DiscMessages.Disc protobuf) { + if (protobuf == null) { + return null; + } + + Disc entity = new Disc(); + + if (protobuf.getId() > 0) { + entity.setId(protobuf.getId()); + } + + entity.setDiscNumber(protobuf.getDiscNumber()); + + // Note: Foreign key relationship (Album) is handled in the service layer + + return entity; + } +} diff --git a/src/main/java/com/mediamanager/model/Disc.java b/src/main/java/com/mediamanager/model/Disc.java new file mode 100644 index 0000000..a7ca6a4 --- /dev/null +++ b/src/main/java/com/mediamanager/model/Disc.java @@ -0,0 +1,47 @@ +package com.mediamanager.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "disc") +public class Disc { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "disc_number", nullable = false) + private Integer discNumber; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "fk_album_id",nullable = false) + private Album album; + + public Disc() { + + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getDiscNumber() { + return discNumber; + } + + public void setDiscNumber(Integer discNumber) { + this.discNumber = discNumber; + } + + public Album getAlbum() { + return album; + } + + public void setAlbum(Album album) { + this.album = album; + } +} diff --git a/src/main/java/com/mediamanager/repository/DiscRepository.java b/src/main/java/com/mediamanager/repository/DiscRepository.java new file mode 100644 index 0000000..69e7510 --- /dev/null +++ b/src/main/java/com/mediamanager/repository/DiscRepository.java @@ -0,0 +1,100 @@ +package com.mediamanager.repository; + +import com.mediamanager.model.Disc; +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 DiscRepository { + private static final Logger logger = LogManager.getLogger(DiscRepository.class); + + private final EntityManagerFactory entityManagerFactory; + + public DiscRepository(EntityManagerFactory entityManagerFactory) { + this.entityManagerFactory = entityManagerFactory; + } + + public Disc save(Disc disc) { + logger.debug("Saving Disc: {}", disc.getDiscNumber()); + EntityManager em = entityManagerFactory.createEntityManager(); + em.getTransaction().begin(); + try { + em.persist(disc); + em.getTransaction().commit(); + logger.debug("Disc has been saved successfully"); + return disc; + } catch (Exception e) { + em.getTransaction().rollback(); + logger.error("Error while saving Disc: {}", e.getMessage()); + throw e; + } finally { + if (em.isOpen()) em.close(); + } + } + + public List findAll() { + logger.debug("Finding All Disc"); + EntityManager em = entityManagerFactory.createEntityManager(); + try{ + return em.createQuery("select d from Disc d", Disc.class).getResultList(); + }finally { + if (em.isOpen()) em.close(); + } + } + + public Optional findById(Integer id) { + logger.debug("Finding Disc with id: {}", id); + EntityManager em = entityManagerFactory.createEntityManager(); + try{ + Disc disc = em.find(Disc.class, id); + return Optional.ofNullable(disc); + }finally { + if (em.isOpen()) em.close(); + } + } + + public Disc update(Disc disc) { + logger.debug("Updating Disc: {}", disc.getDiscNumber()); + EntityManager em = entityManagerFactory.createEntityManager(); + em.getTransaction().begin(); + try { + Disc updated = em.merge(disc); + em.getTransaction().commit(); + logger.debug("Disc has been updated successfully"); + return updated; + } catch (Exception e) { + em.getTransaction().rollback(); + logger.error("Error while updating Disc: {}", e.getMessage()); + throw e; + } finally { + if (em.isOpen()) em.close(); + } + } + + public boolean deleteById(Integer id){ + logger.debug("Deleting Disc with id: {}", id); + EntityManager em = entityManagerFactory.createEntityManager(); + em.getTransaction().begin(); + try{ + Disc disc = em.find(Disc.class, id); + if (disc == null) { + em.getTransaction().rollback(); + return false; + } + em.remove(disc); + em.getTransaction().commit(); + logger.debug("Disc has been deleted successfully"); + return true; + } catch (Exception e) { + em.getTransaction().rollback(); + logger.error("Error while deleting Disc: {}", e.getMessage()); + throw e; + } finally { + if (em.isOpen()) em.close(); + } + } +} diff --git a/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java b/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java index 1f1cb81..a849a5d 100644 --- a/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java +++ b/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java @@ -3,6 +3,7 @@ package com.mediamanager.service.delegate; import com.google.protobuf.ByteString; import com.mediamanager.protocol.TransportProtocol; import com.mediamanager.repository.*; +import com.mediamanager.repository.DiscRepository; import com.mediamanager.service.album.AlbumService; import com.mediamanager.service.albumart.AlbumArtService; import com.mediamanager.service.albumhasartist.AlbumHasArtistService; @@ -15,6 +16,7 @@ import com.mediamanager.repository.GenreRepository; import com.mediamanager.service.artist.ArtistService; import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.disc.DiscService; import com.mediamanager.service.genre.GenreService; import com.mediamanager.service.samplingrate.SamplingRateService; import jakarta.persistence.EntityManagerFactory; @@ -100,6 +102,10 @@ public class DelegateActionManager { AlbumHasGenreService albumHasGenreService = new AlbumHasGenreService(albumHasGenreRepository, albumRepository, genreRepository); serviceLocator.register(AlbumHasGenreService.class, albumHasGenreService); + DiscRepository discRepository = new DiscRepository(entityManagerFactory); + DiscService discService = new DiscService(discRepository, albumRepository); + serviceLocator.register(DiscService.class, discService); + serviceLocator.logRegisteredServices(); logger.info("Services initialized successfully"); diff --git a/src/main/java/com/mediamanager/service/delegate/handler/disc/CreateDiscHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/disc/CreateDiscHandler.java new file mode 100644 index 0000000..d78d907 --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/disc/CreateDiscHandler.java @@ -0,0 +1,61 @@ +package com.mediamanager.service.delegate.handler.disc; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.DiscMapper; +import com.mediamanager.model.Disc; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.DiscMessages; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.disc.DiscService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Action("disc.create") +public class CreateDiscHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(CreateDiscHandler.class); + private final DiscService discService; + + public CreateDiscHandler(DiscService discService) { + this.discService = discService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException { + try { + DiscMessages.CreateDiscRequest createRequest = + DiscMessages.CreateDiscRequest.parseFrom(requestPayload); + + Disc disc = discService.createDisc( + createRequest.getDiscNumber(), + createRequest.getFkAlbumId() > 0 ? createRequest.getFkAlbumId() : null + ); + + DiscMessages.Disc discProto = DiscMapper.toProtobuf(disc); + DiscMessages.CreateDiscResponse createDiscResponse = DiscMessages.CreateDiscResponse.newBuilder() + .setDisc(discProto) + .build(); + return TransportProtocol.Response.newBuilder() + .setPayload(createDiscResponse.toByteString()); + } catch (IllegalArgumentException e) { + logger.error("Validation error", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(400) + .setPayload(ByteString.copyFromUtf8("Invalid request")); + + } catch (InvalidProtocolBufferException e) { + logger.error("Invalid CreateDiscRequest payload", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(400) + .setPayload(ByteString.copyFromUtf8("Invalid request payload")); + + } catch (Exception e) { + logger.error("Error creating disc", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(ByteString.copyFromUtf8("Internal server error")); + } + } + } +} diff --git a/src/main/java/com/mediamanager/service/delegate/handler/disc/DeleteDiscHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/disc/DeleteDiscHandler.java new file mode 100644 index 0000000..cc52f0e --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/disc/DeleteDiscHandler.java @@ -0,0 +1,59 @@ +package com.mediamanager.service.delegate.handler.disc; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.DiscMessages; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.disc.DiscService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Action("disc.delete") +public class DeleteDiscHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(DeleteDiscHandler.class); + + private final DiscService discService; + + public DeleteDiscHandler(DiscService discService) { + this.discService = discService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) + throws InvalidProtocolBufferException { + + try { + DiscMessages.DeleteDiscRequest deleteRequest = + DiscMessages.DeleteDiscRequest.parseFrom(requestPayload); + int id = deleteRequest.getId(); + boolean success = discService.deleteDisc(id); + DiscMessages.DeleteDiscResponse deleteResponse; + if (success) { + deleteResponse = DiscMessages.DeleteDiscResponse.newBuilder() + .setMessage("Disc deleted successfully") + .build(); + return TransportProtocol.Response.newBuilder() + .setPayload(deleteResponse.toByteString()); + } else { + deleteResponse = DiscMessages.DeleteDiscResponse.newBuilder() + .setMessage("Disc not found") + .build(); + + return TransportProtocol.Response.newBuilder() + .setStatusCode(404) + .setPayload(deleteResponse.toByteString()); + } + } catch (Exception e) { + logger.error("Error deleting disc", e); + DiscMessages.DeleteDiscResponse deleteResponse = + DiscMessages.DeleteDiscResponse.newBuilder() + .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/disc/GetDiscByIdHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/disc/GetDiscByIdHandler.java new file mode 100644 index 0000000..10a1f92 --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/disc/GetDiscByIdHandler.java @@ -0,0 +1,56 @@ +package com.mediamanager.service.delegate.handler.disc; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.DiscMapper; +import com.mediamanager.model.Disc; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.DiscMessages; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.disc.DiscService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Optional; + +@Action(value = "disc.getById") +public class GetDiscByIdHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(GetDiscByIdHandler.class); + private final DiscService discService; + + public GetDiscByIdHandler(DiscService discService) { + this.discService = discService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) + throws InvalidProtocolBufferException{ + + try{ + DiscMessages.GetDiscByIdRequest getByIdRequest = + DiscMessages.GetDiscByIdRequest.parseFrom(requestPayload); + int id = getByIdRequest.getId(); + + Optional discOpt = discService.getDiscById(id); + + if (discOpt.isEmpty()){ + logger.warn("Disc not found with ID: {}", id); + return TransportProtocol.Response.newBuilder() + .setStatusCode(404) + .setPayload(ByteString.copyFromUtf8("Disc not found")); + } + DiscMessages.Disc discProto = DiscMapper.toProtobuf(discOpt.get()); + DiscMessages.GetDiscByIdResponse getByIdResponse = DiscMessages.GetDiscByIdResponse.newBuilder() + .setDisc(discProto) + .build(); + return TransportProtocol.Response.newBuilder() + .setPayload(getByIdResponse.toByteString()); + } catch (Exception e) { + logger.error("Error getting disc 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/disc/GetDiscHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/disc/GetDiscHandler.java new file mode 100644 index 0000000..17a5929 --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/disc/GetDiscHandler.java @@ -0,0 +1,47 @@ +package com.mediamanager.service.delegate.handler.disc; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.DiscMapper; +import com.mediamanager.model.Disc; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.DiscMessages; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.disc.DiscService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.List; + +@Action("disc.getAll") +public class GetDiscHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(GetDiscHandler.class); + + private final DiscService discService; + + public GetDiscHandler(DiscService discService){this.discService = discService;} + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException { + try{ + List discs = discService.getAllDiscs(); + DiscMessages.GetDiscsResponse.Builder responseBuilder = DiscMessages.GetDiscsResponse.newBuilder(); + + for (Disc disc : discs) { + DiscMessages.Disc discProto = DiscMapper.toProtobuf(disc); + responseBuilder.addDiscs(discProto); + } + DiscMessages.GetDiscsResponse getDiscsResponse = responseBuilder.build(); + + return TransportProtocol.Response.newBuilder() + .setPayload(getDiscsResponse.toByteString()); + + }catch (Exception e){ + logger.error("Error getting discs", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage())); + } + } +} diff --git a/src/main/java/com/mediamanager/service/delegate/handler/disc/UpdateDiscHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/disc/UpdateDiscHandler.java new file mode 100644 index 0000000..1648053 --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/disc/UpdateDiscHandler.java @@ -0,0 +1,72 @@ +package com.mediamanager.service.delegate.handler.disc; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.DiscMapper; +import com.mediamanager.model.Disc; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.DiscMessages; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import com.mediamanager.service.disc.DiscService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Optional; + +@Action("disc.update") +public class UpdateDiscHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(UpdateDiscHandler.class); + private final DiscService discService; + + public UpdateDiscHandler(DiscService discService) { + this.discService = discService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) + throws InvalidProtocolBufferException { + try { + DiscMessages.UpdateDiscRequest updateRequest = + DiscMessages.UpdateDiscRequest.parseFrom(requestPayload); + + int id = updateRequest.getId(); + Integer discNumber = updateRequest.getDiscNumber(); + Integer albumId = updateRequest.getFkAlbumId() > 0 ? updateRequest.getFkAlbumId() : null; + + Optional discOpt = discService.updateDisc( + id, + discNumber, + albumId + ); + + if (discOpt.isEmpty()) { + logger.warn("Disc not found with ID: {}", id); + return TransportProtocol.Response.newBuilder() + .setStatusCode(404) + .setPayload(ByteString.copyFromUtf8("Disc not found")); + } + + DiscMessages.Disc discProto = DiscMapper.toProtobuf(discOpt.get()); + + DiscMessages.UpdateDiscResponse updateResponse = + DiscMessages.UpdateDiscResponse.newBuilder() + .setDisc(discProto) + .build(); + + return TransportProtocol.Response.newBuilder() + .setPayload(updateResponse.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 updating disc", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage())); + } + } +} diff --git a/src/main/java/com/mediamanager/service/disc/DiscService.java b/src/main/java/com/mediamanager/service/disc/DiscService.java new file mode 100644 index 0000000..4dd114b --- /dev/null +++ b/src/main/java/com/mediamanager/service/disc/DiscService.java @@ -0,0 +1,98 @@ +package com.mediamanager.service.disc; + +import com.mediamanager.model.Album; +import com.mediamanager.model.Disc; +import com.mediamanager.repository.AlbumRepository; +import com.mediamanager.repository.DiscRepository; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.List; +import java.util.Optional; + +public class DiscService { + private static final Logger logger = LogManager.getLogger(DiscService.class); + private final DiscRepository repository; + private final AlbumRepository albumRepository; + + public DiscService(DiscRepository repository, AlbumRepository albumRepository) { + this.repository = repository; + this.albumRepository = albumRepository; + } + + public Disc createDisc(Integer discNumber, Integer albumId) { + logger.debug("Creating disc with number: {}", discNumber); + if (discNumber == null) { + throw new IllegalArgumentException("Disc number cannot be null"); + } + if (albumId == null) { + throw new IllegalArgumentException("Album ID cannot be null"); + } + + Disc disc = new Disc(); + disc.setDiscNumber(discNumber); + + // Set Album (required) + Optional album = albumRepository.findById(albumId); + if (album.isEmpty()) { + throw new IllegalArgumentException("Album not found with id: " + albumId); + } + disc.setAlbum(album.get()); + + return repository.save(disc); + } + + public List getAllDiscs() { + logger.info("Getting all discs"); + return repository.findAll(); + } + + public Optional getDiscById(Integer id) { + if (id == null) { + throw new IllegalArgumentException("ID cannot be null"); + } + logger.info("Getting disc by id: {}", id); + return repository.findById(id); + } + + public Optional updateDisc(Integer id, Integer discNumber, Integer albumId) { + if (id == null) { + throw new IllegalArgumentException("ID cannot be null"); + } + if (discNumber == null) { + throw new IllegalArgumentException("Disc number cannot be null"); + } + if (albumId == null) { + throw new IllegalArgumentException("Album ID cannot be null"); + } + + logger.info("Updating disc with id: {}", id); + + Optional existingDisc = repository.findById(id); + if (existingDisc.isEmpty()) { + logger.warn("Disc not found with id: {}", id); + return Optional.empty(); + } + + Disc disc = existingDisc.get(); + disc.setDiscNumber(discNumber); + + // Update Album + Optional album = albumRepository.findById(albumId); + if (album.isEmpty()) { + throw new IllegalArgumentException("Album not found with id: " + albumId); + } + disc.setAlbum(album.get()); + + Disc updatedDisc = repository.update(disc); + return Optional.of(updatedDisc); + } + + public boolean deleteDisc(Integer id) { + if (id == null) { + throw new IllegalArgumentException("Disc id cannot be null"); + } + logger.info("Deleting disc: {}", id); + return repository.deleteById(id); + } +} diff --git a/src/main/proto/disc.proto b/src/main/proto/disc.proto new file mode 100644 index 0000000..90ad694 --- /dev/null +++ b/src/main/proto/disc.proto @@ -0,0 +1,54 @@ +syntax = "proto3"; + +option java_package = "com.mediamanager.protocol.messages"; +option java_outer_classname = "DiscMessages"; + +package mediamanager.messages; + +message Disc{ + int32 id = 1; + int32 disc_number = 2; + int32 fk_album_id = 3; +} + +message CreateDiscRequest { + int32 disc_number = 1; + int32 fk_album_id = 2; +} + +message CreateDiscResponse { + Disc disc = 1; +} + +message GetDiscsRequest { +} + +message GetDiscsResponse { + repeated Disc discs = 1; +} + +message GetDiscByIdRequest { + int32 id = 1; +} + +message GetDiscByIdResponse { + Disc disc = 1; +} + +message UpdateDiscRequest { + int32 id = 1; + int32 disc_number = 2; + int32 fk_album_id = 3; +} + +message UpdateDiscResponse { + Disc disc = 1; +} + +message DeleteDiscRequest { + int32 id = 1; +} + +message DeleteDiscResponse { + string message = 1; +} \ No newline at end of file