diff --git a/src/main/java/com/mediamanager/mapper/ArtistMapper.java b/src/main/java/com/mediamanager/mapper/ArtistMapper.java new file mode 100644 index 0000000..29f2ce9 --- /dev/null +++ b/src/main/java/com/mediamanager/mapper/ArtistMapper.java @@ -0,0 +1,41 @@ +package com.mediamanager.mapper; + +import com.mediamanager.model.Artist; +import com.mediamanager.protocol.messages.ArtistMessages; + + +public class ArtistMapper { + public static ArtistMessages.Artist toProtobuf(Artist entity){ + if (entity == null) { + return null; + } + + String name = entity.getName(); + if (name == null) { + throw new IllegalArgumentException("Artist name cannot be null"); + } + + ArtistMessages.Artist.Builder builder = ArtistMessages.Artist.newBuilder() + .setName(name); + + // Only set ID when it's present and valid (> 0). Avoids NPE for null IDs. + Integer id = entity.getId(); + if (id != null && id > 0) { + builder.setId(id); + } + + return builder.build(); + } + public static Artist toEntity(ArtistMessages.Artist protobuf) { + if (protobuf == null) { + return null; + } + Artist entity = new Artist(); + + if (protobuf.getId() > 0) { + entity.setId(protobuf.getId()); + } + entity.setName(protobuf.getName()); + return entity; + } +} diff --git a/src/main/java/com/mediamanager/model/Artist.java b/src/main/java/com/mediamanager/model/Artist.java new file mode 100644 index 0000000..22fe490 --- /dev/null +++ b/src/main/java/com/mediamanager/model/Artist.java @@ -0,0 +1,27 @@ +package com.mediamanager.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "artist") +public class Artist { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + private String name; + + public Integer getId() { + return id; + } + public void setId(Integer id) { + this.id = id; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/com/mediamanager/repository/ArtistRepository.java b/src/main/java/com/mediamanager/repository/ArtistRepository.java new file mode 100644 index 0000000..60d0b9d --- /dev/null +++ b/src/main/java/com/mediamanager/repository/ArtistRepository.java @@ -0,0 +1,104 @@ +package com.mediamanager.repository; +import com.mediamanager.model.Artist; +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 ArtistRepository { + private static final Logger logger = LogManager.getLogger(ArtistRepository.class); + + private final EntityManagerFactory entityManagerFactory; + + public ArtistRepository(EntityManagerFactory entityManagerFactory) { + this.entityManagerFactory = entityManagerFactory; + } + + public Artist save(Artist artist){ + logger.debug("Saving Artist: {}", artist.getName()); + EntityManager em = entityManagerFactory.createEntityManager(); + em.getTransaction().begin(); + try { + em.persist(artist); + em.getTransaction().commit(); + logger.debug("Artist saved with ID: {}", artist.getId()); + return artist; + } catch (Exception e) { + em.getTransaction().rollback(); + logger.error("Error saving Artist", e); + throw e; + } finally { + if (em.isOpen()) em.close(); + } + } + + public List findAll(){ + logger.debug("Finding all Artists"); + EntityManager em = entityManagerFactory.createEntityManager(); + try { + return em + .createQuery("SELECT a FROM Artist a ORDER BY a.name", Artist.class) + .getResultList(); + } finally { + if (em.isOpen()) em.close(); + } + } + + public Optional findById(Integer id){ + logger.debug("Finding artist by ID: {}", id); + EntityManager em = entityManagerFactory.createEntityManager(); + try { + Artist artist = em.find(Artist.class, id); + return Optional.ofNullable(artist); + } finally { + if (em.isOpen()) em.close(); + } + + } + + public Artist update(Artist artist){ + logger.debug("Updating artist ID: {}", artist.getId()); + EntityManager em = entityManagerFactory.createEntityManager(); + em.getTransaction().begin(); + try { + Artist updated = em.merge(artist); + em.getTransaction().commit(); + logger.debug("Artist updated successfully"); + return updated; + } catch (Exception e) { + em.getTransaction().rollback(); + logger.error("Error updating artist", e); + throw e; + } finally { + if (em.isOpen()) em.close(); + } + } + + public boolean deleteById(Integer id){ + logger.debug("Deleting Artist by ID: {}", id); + EntityManager em = entityManagerFactory.createEntityManager(); + em.getTransaction().begin(); + try { + Artist artist = em.find(Artist.class, id); + if (artist == null) { + em.getTransaction().rollback(); + return false; + } + em.remove(artist); + em.getTransaction().commit(); + logger.debug("Artist deleted successfully"); + return true; + } catch (Exception e) { + em.getTransaction().rollback(); + logger.error("Error deleting artist", e); + throw e; + } finally { + if (em.isOpen()) em.close(); + } + } + } + + diff --git a/src/main/java/com/mediamanager/service/artist/ArtistService.java b/src/main/java/com/mediamanager/service/artist/ArtistService.java new file mode 100644 index 0000000..4686030 --- /dev/null +++ b/src/main/java/com/mediamanager/service/artist/ArtistService.java @@ -0,0 +1,65 @@ +package com.mediamanager.service.artist; + +import com.mediamanager.model.Artist; +import com.mediamanager.repository.ArtistRepository; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.List; +import java.util.Optional; + +public class ArtistService { + private static final Logger logger = LogManager.getLogger(ArtistService.class); + private final ArtistRepository artistRepository; + + public ArtistService(ArtistRepository artistRepository) { + this.artistRepository = artistRepository; + } + + public Artist createArtist(String name){ + logger.info("Creating artist: {}", name); + if (name == null || name.trim().isEmpty()) { + throw new IllegalArgumentException("Artist name cannot be empty"); + } + Artist artist = new Artist(); + artist.setName(name.trim()); + return artistRepository.save(artist); + } + + public List getAllArtists(){ + logger.info("Getting all artists"); + return artistRepository.findAll(); + } + + public Optional getArtistById(Integer id){ + logger.info("Getting artist by ID: {}", id); + return artistRepository.findById(id); + } + + public Optional updateArtist(Integer id, String name){ + logger.info("Updating artist ID {}: {}", id, name); + + if (name == null || name.trim().isEmpty()) { + throw new IllegalArgumentException("Artist name cannot be empty"); + } + + Optional existingArtist = artistRepository.findById(id); + + if(existingArtist.isEmpty()){ + logger.warn("Artist not found with ID: {}", id); + return Optional.empty(); + } + Artist artist = existingArtist.get(); + artist.setName(name.trim()); + Artist updatedArtist = artistRepository.update(artist); + return Optional.of(updatedArtist); + } + + public boolean deleteArtist(Integer id){ + logger.info("Deleting artist ID: {}", id); + return artistRepository.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 eb4ae76..ee5ae38 100644 --- a/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java +++ b/src/main/java/com/mediamanager/service/delegate/DelegateActionManager.java @@ -5,6 +5,9 @@ import com.mediamanager.protocol.TransportProtocol; import com.mediamanager.repository.ComposerRepository; import com.mediamanager.repository.GenreRepository; import com.mediamanager.service.composer.ComposerService; +import com.mediamanager.repository.ArtistRepository; +import com.mediamanager.repository.GenreRepository; +import com.mediamanager.service.artist.ArtistService; import com.mediamanager.service.delegate.annotation.Action; import com.mediamanager.service.genre.GenreService; @@ -50,6 +53,10 @@ public class DelegateActionManager { serviceLocator.register(GenreService.class, genreService); + ArtistRepository artistRepository = new ArtistRepository(entityManagerFactory); + ArtistService artistService = new ArtistService(artistRepository); + + serviceLocator.register(ArtistService.class, artistService); diff --git a/src/main/java/com/mediamanager/service/delegate/handler/artist/CreateArtistHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/artist/CreateArtistHandler.java new file mode 100644 index 0000000..268a4bd --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/artist/CreateArtistHandler.java @@ -0,0 +1,50 @@ +package com.mediamanager.service.delegate.handler.artist; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.ArtistMapper; +import com.mediamanager.model.Artist; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.ArtistMessages; +import com.mediamanager.service.artist.ArtistService; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Action("artist.create") +public class CreateArtistHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(CreateArtistHandler.class); + private final ArtistService artistService; + + public CreateArtistHandler(ArtistService artistService) { + this.artistService = artistService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException { + try{ + ArtistMessages.CreateArtistRequest createRequest = + ArtistMessages.CreateArtistRequest.parseFrom(requestPayload); + Artist artist = artistService.createArtist(createRequest.getName()); + ArtistMessages.Artist artistProto = ArtistMapper.toProtobuf(artist); + ArtistMessages.CreateArtistResponse createArtistResponse = ArtistMessages.CreateArtistResponse.newBuilder() + .setArtist(artistProto) + .build(); + return TransportProtocol.Response.newBuilder() + .setPayload(createArtistResponse.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 artist", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage())); + } + } +} + diff --git a/src/main/java/com/mediamanager/service/delegate/handler/artist/DeleteArtistHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/artist/DeleteArtistHandler.java new file mode 100644 index 0000000..a3d3c72 --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/artist/DeleteArtistHandler.java @@ -0,0 +1,62 @@ +package com.mediamanager.service.delegate.handler.artist; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.ArtistMessages; +import com.mediamanager.service.artist.ArtistService; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Action("artist.delete") +public class DeleteArtistHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(DeleteArtistHandler.class); + + private final ArtistService artistService; + + public DeleteArtistHandler(ArtistService artistService) { + this.artistService = artistService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) + throws InvalidProtocolBufferException { + + try { + ArtistMessages.DeleteArtistRequest deleteRequest = + ArtistMessages.DeleteArtistRequest.parseFrom(requestPayload); + int id = deleteRequest.getId(); + boolean success = artistService.deleteArtist(id); + ArtistMessages.DeleteArtistResponse deleteResponse; + if (success) { + deleteResponse = ArtistMessages.DeleteArtistResponse.newBuilder() + .setSuccess(true) + .setMessage("Artist deleted successfully") + .build(); + return TransportProtocol.Response.newBuilder() + .setPayload(deleteResponse.toByteString()); + } else { + deleteResponse = ArtistMessages.DeleteArtistResponse.newBuilder() + .setSuccess(false) + .setMessage("Artist not found") + .build(); + + return TransportProtocol.Response.newBuilder() + .setStatusCode(404) + .setPayload(deleteResponse.toByteString()); + } + } catch (Exception e) { + logger.error("Error deleting artist", e); + ArtistMessages.DeleteArtistResponse deleteResponse = + ArtistMessages.DeleteArtistResponse.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/artist/GetArtistByIdHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/artist/GetArtistByIdHandler.java new file mode 100644 index 0000000..d98b48e --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/artist/GetArtistByIdHandler.java @@ -0,0 +1,56 @@ +package com.mediamanager.service.delegate.handler.artist; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.ArtistMapper; +import com.mediamanager.model.Artist; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.ArtistMessages; +import com.mediamanager.service.artist.ArtistService; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Optional; + +@Action(value = "artist.getById") +public class GetArtistByIdHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(GetArtistByIdHandler.class); + private final ArtistService artistService; + + public GetArtistByIdHandler(ArtistService artistService) { + this.artistService = artistService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) + throws InvalidProtocolBufferException{ + + try{ + ArtistMessages.GetArtistByIdRequest getByIdRequest = + ArtistMessages.GetArtistByIdRequest.parseFrom(requestPayload); + int id = getByIdRequest.getId(); + + Optional artistOpt = artistService.getArtistById(id); + + if (artistOpt.isEmpty()){ + logger.warn("Artist not found with ID: {}", id); + return TransportProtocol.Response.newBuilder() + .setStatusCode(404) + .setPayload(ByteString.copyFromUtf8("Artist not found")); + } + ArtistMessages.Artist artistProto = ArtistMapper.toProtobuf(artistOpt.get()); + ArtistMessages.GetArtistByIdResponse getByIdResponse = ArtistMessages.GetArtistByIdResponse.newBuilder() + .setArtist(artistProto) + .build(); + return TransportProtocol.Response.newBuilder() + .setPayload(getByIdResponse.toByteString()); + } catch (Exception e) { + logger.error("Error getting artist 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/artist/GetArtistHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/artist/GetArtistHandler.java new file mode 100644 index 0000000..bf91fff --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/artist/GetArtistHandler.java @@ -0,0 +1,48 @@ +package com.mediamanager.service.delegate.handler.artist; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.ArtistMapper; +import com.mediamanager.model.Artist; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.ArtistMessages; +import com.mediamanager.service.artist.ArtistService; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.List; + + +@Action("artist.getAll") +public class GetArtistHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(GetArtistHandler.class); + + private final ArtistService artistService; + + public GetArtistHandler(ArtistService artistService){this.artistService = artistService;} + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException { + try{ + List artists = artistService.getAllArtists(); + ArtistMessages.GetArtistsResponse.Builder responseBuilder = ArtistMessages.GetArtistsResponse.newBuilder(); + + for (Artist artist : artists) { + ArtistMessages.Artist artistProto = ArtistMapper.toProtobuf(artist); + responseBuilder.addArtists(artistProto); + } + ArtistMessages.GetArtistsResponse getArtistsResponse = responseBuilder.build(); + + return TransportProtocol.Response.newBuilder() + .setPayload(getArtistsResponse.toByteString()); + + }catch (Exception e){ + logger.error("Error getting artists", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage())); + } + } +} diff --git a/src/main/java/com/mediamanager/service/delegate/handler/artist/UpdateArtistHandler.java b/src/main/java/com/mediamanager/service/delegate/handler/artist/UpdateArtistHandler.java new file mode 100644 index 0000000..69c3cd6 --- /dev/null +++ b/src/main/java/com/mediamanager/service/delegate/handler/artist/UpdateArtistHandler.java @@ -0,0 +1,65 @@ +package com.mediamanager.service.delegate.handler.artist; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mediamanager.mapper.ArtistMapper; +import com.mediamanager.model.Artist; +import com.mediamanager.protocol.TransportProtocol; +import com.mediamanager.protocol.messages.ArtistMessages; +import com.mediamanager.service.artist.ArtistService; +import com.mediamanager.service.delegate.ActionHandler; +import com.mediamanager.service.delegate.annotation.Action; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Optional; + +@Action("artist.update") +public class UpdateArtistHandler implements ActionHandler { + private static final Logger logger = LogManager.getLogger(UpdateArtistHandler.class); + private final ArtistService artistService; + + public UpdateArtistHandler(ArtistService artistService) { + this.artistService = artistService; + } + + @Override + public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException { + try{ + ArtistMessages.UpdateArtistRequest updateRequest = + ArtistMessages.UpdateArtistRequest.parseFrom(requestPayload); + + int id = updateRequest.getId(); + String newName = updateRequest.getName(); + + Optional artistOpt = artistService.updateArtist(id, newName); + + if(artistOpt.isEmpty()){ + logger.warn("Artist not found with ID: {}", id); + return TransportProtocol.Response.newBuilder() + .setStatusCode(404) + .setPayload(ByteString.copyFromUtf8("Artist not found")); + } + + ArtistMessages.Artist artistProto = ArtistMapper.toProtobuf(artistOpt.get()); + + ArtistMessages.UpdateArtistResponse updateResponse = ArtistMessages.UpdateArtistResponse.newBuilder() + .setArtist(artistProto) + .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 artist", e); + return TransportProtocol.Response.newBuilder() + .setStatusCode(500) + .setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage())); + } + } +} diff --git a/src/main/proto/artist.proto b/src/main/proto/artist.proto new file mode 100644 index 0000000..254e7f7 --- /dev/null +++ b/src/main/proto/artist.proto @@ -0,0 +1,53 @@ +syntax = "proto3"; + +option java_package = "com.mediamanager.protocol.messages"; +option java_outer_classname = "ArtistMessages"; + +package mediamanager.messages; + +message Artist { + int32 id = 1; + string name = 2; +} + +message CreateArtistRequest { + string name = 1; +} + +message CreateArtistResponse { + Artist artist = 1; +} + +message GetArtistsRequest { + +} + +message GetArtistsResponse { + repeated Artist artists = 1; +} + +message GetArtistByIdRequest { + int32 id = 1; +} + +message GetArtistByIdResponse { + Artist artist = 1; +} + +message UpdateArtistRequest { + int32 id = 1; + string name = 2; // Novo nome +} + +message UpdateArtistResponse { + Artist Artist = 1; +} + +message DeleteArtistRequest { + int32 id = 1; +} + +message DeleteArtistResponse { + bool success = 1; + string message = 2; +}