Implement bit-rate management feature

Add complete CRUD functionality for bit-rate management following the same pattern as bit-depth:
  - Create BitRate entity model with JPA annotations
  - Implement BitRateRepository with full CRUD operations
  - Add BitRateService with validation and business logic
  - Create BitRateMapper for protobuf/entity conversion
  - Implement action handlers: Create, GetAll, GetById, Update, Delete
  - Define bitrate.proto protobuf message definitions
  - Register BitRateService in DelegateActionManager

  🤖 Generated with [Claude Code](https://claude.com/claude-code)

  Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Gustavo Henrique Santos Souza de Miranda 2025-12-05 20:43:04 -03:00
parent 8c8b8ec765
commit 2294a57ffd
11 changed files with 575 additions and 0 deletions

View File

@ -0,0 +1,39 @@
package com.mediamanager.mapper;
import com.mediamanager.model.BitRate;
import com.mediamanager.protocol.messages.BitRateMessages;
public class BitRateMapper {
public static BitRateMessages.BitRate toProtobuf(BitRate entity) {
if (entity == null) {
return null;
}
String value = entity.getValue();
if (value == null) {
throw new IllegalArgumentException("Bit rate value cannot be null");
}
BitRateMessages.BitRate.Builder builder = BitRateMessages.BitRate.newBuilder()
.setValue(value);
Integer id = entity.getId();
if (id != null && id > 0) {
builder.setId(id);
}
return builder.build();
}
public static BitRate toEntity(BitRateMessages.BitRate protobuf) {
if (protobuf == null) {
return null;
}
BitRate entity = new BitRate();
if (protobuf.getId() > 0) {
entity.setId(protobuf.getId());
}
entity.setValue(protobuf.getValue());
return entity;
}
}

View File

@ -0,0 +1,31 @@
package com.mediamanager.model;
import jakarta.persistence.*;
@Entity
@Table(name = "bit_rate")
public class BitRate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false)
private String value;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,101 @@
package com.mediamanager.repository;
import com.mediamanager.model.BitRate;
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 BitRateRepository {
private static final Logger logger = LogManager.getLogger(BitRateRepository.class);
private final EntityManagerFactory entityManagerFactory;
public BitRateRepository(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
public BitRate save(BitRate bitRate) {
logger.debug("Saving BitRate: {}", bitRate.getValue());
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
try {
em.persist(bitRate);
em.getTransaction().commit();
logger.debug("BitRate saved with ID: {}", bitRate.getId());
return bitRate;
} catch (Exception e) {
em.getTransaction().rollback();
logger.error("Error saving BitRate", e);
throw e;
} finally {
if (em.isOpen()) em.close();
}
}
public List<BitRate> findAll(){
logger.debug("Finding all BitRates");
EntityManager em = entityManagerFactory.createEntityManager();
try{
return em.createQuery("SELECT b FROM BitRate b ORDER BY b.value", BitRate.class).getResultList();
}finally {
if (em.isOpen()) em.close();
}
}
public Optional<BitRate> findById(Integer id){
logger.debug("Finding BitRate by ID: {}", id);
EntityManager em = entityManagerFactory.createEntityManager();
try{
BitRate bitRate = em.find(BitRate.class, id);
return Optional.ofNullable(bitRate);
} finally {
if (em.isOpen()) em.close();
}
}
public BitRate update(BitRate bitRate){
logger.debug("Updating BitRate ID: {}", bitRate.getId());
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
try{
BitRate updated = em.merge(bitRate);
em.getTransaction().commit();
logger.debug("BitRate updated with ID: {}", bitRate.getId());
return updated;
} catch (Exception e) {
em.getTransaction().rollback();
logger.error("Error updating BitRate", e);
throw e;
} finally {
if (em.isOpen()) em.close();
}
}
public boolean deleteById(Integer id){
logger.debug("Deleting BitRate by ID: {}", id);
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
try{
BitRate bitRate = em.find(BitRate.class, id);
if (bitRate == null) {
em.getTransaction().rollback();
return false;
}
em.remove(bitRate);
em.getTransaction().commit();
logger.debug("BitRate deleted successfully");
return true;
} catch (Exception e) {
em.getTransaction().rollback();
logger.error("Error deleting BitRate", e);
throw e;
} finally {
if (em.isOpen()) em.close();
}
}
}

View File

@ -0,0 +1,65 @@
package com.mediamanager.service.bitrate;
import com.mediamanager.model.BitRate;
import com.mediamanager.repository.BitRateRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
import java.util.Optional;
public class BitRateService {
private static final Logger logger = LogManager.getLogger(BitRateService.class);
private final BitRateRepository bitRateRepository;
public BitRateService(BitRateRepository bitRateRepository) {
this.bitRateRepository = bitRateRepository;
}
public BitRate createBitRate(String value){
logger.info("Creating bit-rate: {}",value);
if (value == null || value.trim().isEmpty()) {
throw new IllegalArgumentException("Bit-rate value cannot be empty");
}
BitRate bitRate = new BitRate();
bitRate.setValue(value.trim());
return bitRateRepository.save(bitRate);
}
public List<BitRate> getAllBitRates(){
logger.info("Getting all bit-rates");
return bitRateRepository.findAll();
}
public Optional<BitRate> getBitRateById(Integer id){
logger.info("Getting bit-rate by ID: {}", id);
return bitRateRepository.findById(id);
}
public Optional<BitRate> updateBitRate(Integer id, String value){
logger.info("Updating bit-rate ID {}: {}", id, value);
if (value == null || value.trim().isEmpty()) {
throw new IllegalArgumentException("Bit-rate value cannot be empty");
}
Optional<BitRate> existingBitRate = bitRateRepository.findById(id);
if(existingBitRate.isEmpty()) {
logger.warn("Bit-rate not found with ID: {}", id);
return Optional.empty();
}
BitRate bitRate = existingBitRate.get();
bitRate.setValue(value.trim());
BitRate updatedBitRate = bitRateRepository.update(bitRate);
return Optional.of(updatedBitRate);
}
public boolean deleteBitRate(Integer id){
logger.info("Deleting bit-rate ID: {}", id);
return bitRateRepository.deleteById(id);
}
}

View File

@ -4,6 +4,7 @@ import com.google.protobuf.ByteString;
import com.mediamanager.protocol.TransportProtocol;
import com.mediamanager.repository.*;
import com.mediamanager.service.bitdepth.BitDepthService;
import com.mediamanager.service.bitrate.BitRateService;
import com.mediamanager.service.composer.ComposerService;
import com.mediamanager.repository.GenreRepository;
import com.mediamanager.service.artist.ArtistService;
@ -65,6 +66,10 @@ public class DelegateActionManager {
BitDepthService bitDepthService = new BitDepthService(bitDepthRepository);
serviceLocator.register(BitDepthService.class, bitDepthService);
BitRateRepository bitRateRepository = new BitRateRepository(entityManagerFactory);
BitRateService bitRateService = new BitRateService(bitRateRepository);
serviceLocator.register(BitRateService.class, bitRateService);
serviceLocator.logRegisteredServices();
logger.info("Services initialized successfully");

View File

@ -0,0 +1,50 @@
package com.mediamanager.service.delegate.handler.bitrate;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.mediamanager.mapper.BitRateMapper;
import com.mediamanager.model.BitRate;
import com.mediamanager.protocol.TransportProtocol;
import com.mediamanager.protocol.messages.BitRateMessages;
import com.mediamanager.service.bitrate.BitRateService;
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("bitrate.create")
public class CreateBitRateHandler implements ActionHandler {
private static final Logger logger = LogManager.getLogger(CreateBitRateHandler.class);
private final BitRateService bitRateService;
public CreateBitRateHandler(BitRateService bitRateService) {
this.bitRateService = bitRateService;
}
@Override
public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException {
try{
BitRateMessages.CreateBitRateRequest createRequest =
BitRateMessages.CreateBitRateRequest.parseFrom(requestPayload);
BitRate bitRate = bitRateService.createBitRate(createRequest.getValue());
BitRateMessages.BitRate BitRateProto = BitRateMapper.toProtobuf(bitRate);
BitRateMessages.CreateBitRateResponse createBitRateResponse = BitRateMessages.CreateBitRateResponse.newBuilder()
.setBitrate(BitRateProto)
.build();
return TransportProtocol.Response.newBuilder()
.setPayload(createBitRateResponse.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 bit-rate", e);
return TransportProtocol.Response.newBuilder()
.setStatusCode(500)
.setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage()));
}
}
}

View File

@ -0,0 +1,62 @@
package com.mediamanager.service.delegate.handler.bitrate;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.mediamanager.protocol.TransportProtocol;
import com.mediamanager.protocol.messages.BitRateMessages;
import com.mediamanager.service.bitrate.BitRateService;
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("bitrate.delete")
public class DeleteBitRateHandler implements ActionHandler {
private static final Logger logger = LogManager.getLogger(DeleteBitRateHandler.class);
private final BitRateService bitRateService;
public DeleteBitRateHandler(BitRateService bitRateService) {
this.bitRateService = bitRateService;
}
@Override
public TransportProtocol.Response.Builder handle(ByteString requestPayload)
throws InvalidProtocolBufferException {
try {
BitRateMessages.DeleteBitRateRequest deleteRequest =
BitRateMessages.DeleteBitRateRequest.parseFrom(requestPayload);
int id = deleteRequest.getId();
boolean success = bitRateService.deleteBitRate(id);
BitRateMessages.DeleteBitRateResponse deleteResponse;
if (success) {
deleteResponse = BitRateMessages.DeleteBitRateResponse.newBuilder()
.setSuccess(true)
.setMessage("Bit-Rate deleted successfully")
.build();
return TransportProtocol.Response.newBuilder()
.setPayload(deleteResponse.toByteString());
} else {
deleteResponse = BitRateMessages.DeleteBitRateResponse.newBuilder()
.setSuccess(false)
.setMessage("Bit-Rate not found")
.build();
return TransportProtocol.Response.newBuilder()
.setStatusCode(404)
.setPayload(deleteResponse.toByteString());
}
} catch (Exception e) {
logger.error("Error deleting bit-rate", e);
BitRateMessages.DeleteBitRateResponse deleteResponse =
BitRateMessages.DeleteBitRateResponse.newBuilder()
.setSuccess(false)
.setMessage("Error: " + e.getMessage())
.build();
return TransportProtocol.Response.newBuilder()
.setStatusCode(500)
.setPayload(deleteResponse.toByteString());
}
}
}

View File

@ -0,0 +1,56 @@
package com.mediamanager.service.delegate.handler.bitrate;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.mediamanager.mapper.BitRateMapper;
import com.mediamanager.model.BitRate;
import com.mediamanager.protocol.TransportProtocol;
import com.mediamanager.protocol.messages.BitRateMessages;
import com.mediamanager.service.bitrate.BitRateService;
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 = "bitrate.getById")
public class GetBitRateByIdHandler implements ActionHandler {
private static final Logger logger = LogManager.getLogger(GetBitRateByIdHandler.class);
private final BitRateService bitRateService;
public GetBitRateByIdHandler(BitRateService bitRateService) {
this.bitRateService = bitRateService;
}
@Override
public TransportProtocol.Response.Builder handle(ByteString requestPayload)
throws InvalidProtocolBufferException{
try{
BitRateMessages.GetBitRateByIdRequest getByIdRequest =
BitRateMessages.GetBitRateByIdRequest.parseFrom(requestPayload);
int id = getByIdRequest.getId();
Optional<BitRate> bitRateOpt = bitRateService.getBitRateById(id);
if (bitRateOpt.isEmpty()){
logger.warn("BitRate not found with ID: {}", id);
return TransportProtocol.Response.newBuilder()
.setStatusCode(404)
.setPayload(ByteString.copyFromUtf8("BitRate not found"));
}
BitRateMessages.BitRate bitRateProto = BitRateMapper.toProtobuf(bitRateOpt.get());
BitRateMessages.GetBitRateByIdResponse getByIdResponse = BitRateMessages.GetBitRateByIdResponse.newBuilder()
.setBitrate(bitRateProto)
.build();
return TransportProtocol.Response.newBuilder()
.setPayload(getByIdResponse.toByteString());
} catch (Exception e) {
logger.error("Error getting bit-rate by ID", e);
return TransportProtocol.Response.newBuilder()
.setStatusCode(500)
.setPayload(ByteString.copyFromUtf8("Error: "+ e.getMessage()));
}
}
}

View File

@ -0,0 +1,48 @@
package com.mediamanager.service.delegate.handler.bitrate;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.mediamanager.mapper.BitRateMapper;
import com.mediamanager.model.BitRate;
import com.mediamanager.protocol.TransportProtocol;
import com.mediamanager.protocol.messages.BitRateMessages;
import com.mediamanager.service.bitrate.BitRateService;
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("bitrate.getAll")
public class GetBitRateHandler implements ActionHandler {
private static final Logger logger = LogManager.getLogger(GetBitRateHandler.class);
private final BitRateService bitRateService;
public GetBitRateHandler(BitRateService bitRateService){this.bitRateService = bitRateService;}
@Override
public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException {
try{
List<BitRate> bitRates = bitRateService.getAllBitRates();
BitRateMessages.GetBitRatesResponse.Builder responseBuilder = BitRateMessages.GetBitRatesResponse.newBuilder();
for (BitRate bitRate : bitRates) {
BitRateMessages.BitRate bitRateProto = BitRateMapper.toProtobuf(bitRate);
responseBuilder.addBitrates(bitRateProto);
}
BitRateMessages.GetBitRatesResponse getBitRatesResponse = responseBuilder.build();
return TransportProtocol.Response.newBuilder()
.setPayload(getBitRatesResponse.toByteString());
}catch (Exception e){
logger.error("Error getting bit-rates", e);
return TransportProtocol.Response.newBuilder()
.setStatusCode(500)
.setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage()));
}
}
}

View File

@ -0,0 +1,65 @@
package com.mediamanager.service.delegate.handler.bitrate;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.mediamanager.mapper.BitRateMapper;
import com.mediamanager.model.BitRate;
import com.mediamanager.protocol.TransportProtocol;
import com.mediamanager.protocol.messages.BitRateMessages;
import com.mediamanager.service.bitrate.BitRateService;
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("bitrate.update")
public class UpdateBitRateHandler implements ActionHandler {
private static final Logger logger = LogManager.getLogger(UpdateBitRateHandler.class);
private final BitRateService bitRateService;
public UpdateBitRateHandler(BitRateService bitRateService) {
this.bitRateService = bitRateService;
}
@Override
public TransportProtocol.Response.Builder handle(ByteString requestPayload) throws InvalidProtocolBufferException {
try{
BitRateMessages.UpdateBitRateRequest updateRequest =
BitRateMessages.UpdateBitRateRequest.parseFrom(requestPayload);
int id = updateRequest.getId();
String newValue = updateRequest.getValue();
Optional<BitRate> bitRateOpt = bitRateService.updateBitRate(id, newValue);
if(bitRateOpt.isEmpty()){
logger.warn("BitRate not found with ID: {}", id);
return TransportProtocol.Response.newBuilder()
.setStatusCode(404)
.setPayload(ByteString.copyFromUtf8("BitRate not found"));
}
BitRateMessages.BitRate bitRateProto = BitRateMapper.toProtobuf(bitRateOpt.get());
BitRateMessages.UpdateBitRateResponse updateResponse = BitRateMessages.UpdateBitRateResponse.newBuilder()
.setBitrate(bitRateProto)
.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 bit-rate", e);
return TransportProtocol.Response.newBuilder()
.setStatusCode(500)
.setPayload(ByteString.copyFromUtf8("Error: " + e.getMessage()));
}
}
}

View File

@ -0,0 +1,53 @@
syntax = "proto3";
option java_package = "com.mediamanager.protocol.messages";
option java_outer_classname = "BitRateMessages";
package mediamanager.messages;
message BitRate{
int32 id =1;
string value = 2;
}
message CreateBitRateRequest{
string value = 1;
}
message CreateBitRateResponse{
BitRate bitrate = 1;
}
message GetBitRatesRequest{
}
message GetBitRatesResponse{
repeated BitRate bitrates = 1;
}
message GetBitRateByIdRequest{
int32 id = 1;
}
message GetBitRateByIdResponse{
BitRate bitrate = 1;
}
message UpdateBitRateRequest{
int32 id = 1;
string value = 2;
}
message UpdateBitRateResponse{
BitRate bitrate = 1;
}
message DeleteBitRateRequest{
int32 id =1;
}
message DeleteBitRateResponse{
bool success = 1;
string message = 2;
}