Commit 069bc18e by Rubén Ramírez

fix: [ServicioRecursos]: Corregidoel servicio debido a la incorrecta división por capas

parent 945fe127
package com.ujaen.tfg.mangaffinity.servicios;
import com.ujaen.tfg.mangaffinity.entidades.*;
import com.ujaen.tfg.mangaffinity.excepciones.CapituloNoExiste;
import com.ujaen.tfg.mangaffinity.excepciones.RecursoNoExiste;
import com.ujaen.tfg.mangaffinity.excepciones.*;
import com.ujaen.tfg.mangaffinity.repositorios.RepositorioCapitulo;
import com.ujaen.tfg.mangaffinity.repositorios.RepositorioRecurso;
import jakarta.validation.Valid;
......@@ -13,6 +12,7 @@ import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
......@@ -24,162 +24,246 @@ public class ServicioRecursos {
@Autowired
RepositorioCapitulo repositorioCapitulo;
/**
* @brief Crea un nuevo recurso en el sistema.
* @param recurso Objeto Recurso con los datos a registrar.
* @throws RecursoYaExiste Si el recurso ya está registrado con el mismo título, autor y fecha de publicación.
*/
@Transactional
public void crearRecurso(@Valid Recurso recurso) {
// Verifica si ya existe un recurso con el mismo título y autor
List<Recurso> recursosExistentes = repositorioRecurso.buscarPorTitulo(recurso.getTitulo());
for (Recurso r : recursosExistentes) {
if (r.getAutor().equals(recurso.getAutor()) &&
r.getFechaPublicacion().equals(recurso.getFechaPublicacion())) {
return;
}
if (repositorioRecurso.existeRecurso(recurso.getTitulo(), recurso.getAutor(), recurso.getFechaPublicacion())) {
throw new RecursoYaExiste();
}
repositorioRecurso.crear(recurso);
}
public Recurso buscarRecursoPorId(Long id) {return repositorioRecurso.buscarPorId(id);}
/**
* @brief Busca un recurso por su ID.
* @param id Identificador del recurso.
* @return Optional con el recurso si existe, vacío si no se encuentra.
*/
public Recurso buscarRecursoPorId(Long id) {
return repositorioRecurso.buscarPorId(id)
.orElseThrow(RecursoNoExiste::new);
}
/**
* @brief Busca recursos por título.
* @param titulo Título del recurso a buscar.
* @return Lista de recursos que coinciden con el título, hasta un máximo de 50.
* Devuelve una lista vacía si el título es nulo o vacío.
*/
public List<Recurso> buscarRecursoPorTitulo(String titulo) {
return repositorioRecurso.buscarPorTitulo(titulo);
if (titulo == null || titulo.trim().isEmpty()) {
return List.of();
}
return repositorioRecurso.buscarPorTitulo(titulo, 50);
}
/**
* @brief Busca recursos por autor.
* @param autor Nombre del autor a buscar.
* @return Lista de recursos del autor, hasta un máximo de 50.
* Devuelve una lista vacía si el autor es nulo o vacío.
*/
public List<Recurso> buscarRecursoPorAutor(String autor) {
return repositorioRecurso.buscarPorAutor(autor);
if (autor == null || autor.trim().isEmpty()) {
return List.of();
}
return repositorioRecurso.buscarPorAutor(autor, 50);
}
/**
* @brief Busca recursos por género.
* @param genero Género del recurso a buscar.
* @return Lista de recursos que pertenecen al género especificado. Devuelve una lista vacía si el género es nulo.
*/
@Transactional(readOnly = true)
public List<Recurso> buscarRecursoPorGenero(Genero genero) {
List<Recurso> recursos = repositorioRecurso.buscarPorGenero(genero);
for (int i = 0; i < recursos.size(); i++) {
recursos.set(i, repositorioRecurso.merge(recursos.get(i)));
recursos.get(i).getGeneros().size();
if (genero == null) {
return List.of();
}
return recursos;
return repositorioRecurso.buscarPorGenero(genero);
}
/**
* @brief Busca recursos publicados dentro de un rango de fechas.
* @param fechaInicio Fecha de inicio del rango (opcional, por defecto 01/01/1900).
* @param fechaFin Fecha de fin del rango (opcional, por defecto la fecha actual).
* @return Lista de recursos publicados en el rango especificado, hasta un máximo de 50.
*/
public List<Recurso> buscarRecursoPorRangoFechas(LocalDate fechaInicio, LocalDate fechaFin) {
return repositorioRecurso.buscarPorRangoFechas(fechaInicio, fechaFin);
if (fechaInicio == null) fechaInicio = LocalDate.of(1900, 1, 1);
if (fechaFin == null) fechaFin = LocalDate.now();
return repositorioRecurso.buscarPorRangoFechas(fechaInicio, fechaFin, 50);
}
/**
* @brief Elimina un recurso del sistema por su ID.
* @param id Identificador del recurso a eliminar.
* @throws RecursoNoExiste Si el recurso no se encuentra en la base de datos.
*/
@Transactional
public boolean borrarRecurso(Long id) {
Recurso recurso = buscarRecursoPorId(id);
if (recurso != null) {
public void borrarRecurso(Long id) {
Recurso recurso = repositorioRecurso.buscarPorId(id)
.orElseThrow(RecursoNoExiste::new);
repositorioRecurso.borrarRecurso(recurso);
return true;
}
return false;
}
/**
* @brief Modifica los datos de un recurso existente.
* @param id Identificador del recurso a modificar.
* @param nuevosDatos Objeto Recurso con los nuevos datos a actualizar.
* @return Recurso actualizado.
* @throws RecursoNoExiste Si el recurso no se encuentra en la base de datos.
* Solo se actualizan los campos no nulos proporcionados en nuevosDatos.
*/
@Transactional
public Recurso modificarRecurso(Long id, Recurso nuevosDatos) {
Recurso recursoExistente = repositorioRecurso.buscarPorId(id);
if (recursoExistente == null) {
throw new RecursoNoExiste();
}
public Recurso modificarRecurso(Long id, Recurso nuevosDatos, byte[] fotoBytes) {
Recurso recursoExistente = repositorioRecurso.buscarPorId(id)
.orElseThrow(RecursoNoExiste::new);
if (nuevosDatos.getTitulo() != null) {
recursoExistente.setTitulo(nuevosDatos.getTitulo());
}
if (nuevosDatos.getDescripcion() != null) {
recursoExistente.setDescripcion(nuevosDatos.getDescripcion());
}
if (nuevosDatos.getFechaPublicacion() != null) {
recursoExistente.setFechaPublicacion(nuevosDatos.getFechaPublicacion());
}
if (nuevosDatos.getAutor() != null) {
recursoExistente.setAutor(nuevosDatos.getAutor());
}
if (nuevosDatos.getGeneros() != null ) {
recursoExistente.setGeneros(nuevosDatos.getGeneros());
}
Optional.ofNullable(nuevosDatos.getTitulo()).ifPresent(recursoExistente::setTitulo);
Optional.ofNullable(nuevosDatos.getDescripcion()).ifPresent(recursoExistente::setDescripcion);
Optional.ofNullable(nuevosDatos.getFechaPublicacion()).ifPresent(recursoExistente::setFechaPublicacion);
Optional.ofNullable(nuevosDatos.getAutor()).ifPresent(recursoExistente::setAutor);
Optional.ofNullable(nuevosDatos.getGeneros()).ifPresent(recursoExistente::setGeneros);
if (fotoBytes != null && fotoBytes.length > 0) recursoExistente.setFoto(fotoBytes);
return repositorioRecurso.modificarRecurso(recursoExistente);
}
/**
* @brief Obtiene la lista completa de recursos.
* @return Lista de todos los recursos almacenados en el sistema.
*/
public List<Recurso> obtenerListadoRecursos() {
return repositorioRecurso.listarRecursos();
}
/**
* @brief Actualiza la foto de un recurso.
* @param recursoId Identificador del recurso a modificar.
* @param nuevaFoto Array de bytes con la nueva imagen del recurso.
* @throws IllegalArgumentException Si la foto es nula o está vacía.
* @throws RecursoNoExiste Si el recurso no se encuentra en la base de datos.
*/
@Transactional
public void actualizarFotoRecurso(Long recursoId, byte[] nuevaFoto) {
Recurso recurso = repositorioRecurso.buscarPorId(recursoId);
if (recurso != null) {
if (nuevaFoto == null || nuevaFoto.length == 0) {
throw new FotoInvalida();
}
Recurso recurso = repositorioRecurso.buscarPorId(recursoId)
.orElseThrow(RecursoNoExiste::new);
recurso.setFoto(nuevaFoto);
repositorioRecurso.modificarRecurso(recurso);
}
}
/**
* @brief Obtiene los capítulos de un recurso según su tipo.
* @param recursoId Identificador del recurso.
* @param tipo Tipo de recurso a filtrar.
* @return Lista de capítulos del recurso para el tipo especificado. Devuelve una lista vacía si no hay capítulos.
* @throws RecursoSinTipo Si el tipo de recurso es nulo.
*/
@Transactional(readOnly = true)
public List<Capitulo> obtenerCapitulosDeRecursoPorTipo(Long recursoId, TipoRecurso tipo) {
return repositorioCapitulo.obtenerCapitulosPorTipo(recursoId, tipo);
if (tipo == null) {
throw new RecursoSinTipo();
}
return Optional.ofNullable(repositorioCapitulo.obtenerCapitulosPorTipo(recursoId, tipo))
.orElse(List.of());
}
/**
* @brief Obtiene todos los capítulos de un recurso.
* @param recursoId Identificador del recurso.
* @return Lista de capítulos asociados al recurso. Devuelve una lista vacía si no hay capítulos.
* Inicializa las fuentes de cada capítulo si la relación es Lazy.
*/
@Transactional
public List<Capitulo> obtenerCapitulosDeRecurso(Long recursoId) {
List<Capitulo> capitulos = repositorioCapitulo.obtenerCapitulosRecurso(recursoId);
List<Capitulo> capitulos = Optional.ofNullable(repositorioCapitulo.obtenerCapitulosRecurso(recursoId))
.orElse(List.of());
capitulos.forEach(capitulo -> capitulo.getFuentes().size());
return capitulos;
}
/**
* @brief Obtiene la lista de todos los géneros disponibles.
* @return Lista de nombres de los géneros en formato de cadena.
*/
public List<String> obtenerGeneros() {
return Arrays.stream(Genero.values())
return List.of(Genero.values()).stream()
.map(Enum::name)
.collect(Collectors.toList());
}
.toList();
}
/**
* @brief Añade un nuevo capítulo a un recurso.
* @param recursoId Identificador del recurso al que se añadirá el capítulo.
* @param nuevoCapitulo Objeto Capitulo con los datos a registrar.
* @throws IllegalArgumentException Si el recursoId es nulo o negativo.
* @throws IllegalArgumentException Si el capítulo es nulo.
* @throws RecursoNoExiste Si el recurso no se encuentra en la base de datos.
* Asigna el recurso al capítulo y establece las relaciones con sus fuentes antes de guardarlo.
*/
@Transactional
public void anadirCapitulo(Long recursoId, Capitulo nuevoCapitulo) {
Recurso recurso = repositorioRecurso.buscarPorId(recursoId);
if (recurso == null) {
throw new RecursoNoExiste();
if (recursoId == null || recursoId < 1) {
throw new IllegalArgumentException("El ID del recurso no puede ser nulo o negativo.");
}
if (nuevoCapitulo == null) {
throw new CapituloInvalido();
}
Recurso recurso = repositorioRecurso.buscarPorId(recursoId)
.orElseThrow(RecursoNoExiste::new);
nuevoCapitulo.setRecurso(recurso);
if (nuevoCapitulo.getFuentes() != null) {
for (FuenteCapitulo fuente : nuevoCapitulo.getFuentes()) {
fuente.setCapitulo(nuevoCapitulo);
}
}
Optional.ofNullable(nuevoCapitulo.getFuentes()).ifPresent(fuentes ->
fuentes.forEach(fuente -> fuente.setCapitulo(nuevoCapitulo))
);
repositorioCapitulo.crearCapitulo(nuevoCapitulo);
}
/**
* Modifica un capítulo existente dentro de un recurso.
* @param recursoId ID del recurso al que pertenece el capítulo.
* @param capituloModificado Entidad Capitulo con los nuevos datos.
* @return Capítulo actualizado.
* @throws RecursoNoExiste Si el recurso no existe.
* @throws CapituloNoExiste Si el capítulo no existe.
*/
@Transactional
public void modificarCapitulo(Capitulo capituloModificado) {
Capitulo capitulo = repositorioCapitulo.buscarPorId(capituloModificado.getId());
if (capitulo == null) {
throw new CapituloNoExiste();
}
public void modificarCapitulo(Long recursoId, Capitulo capituloModificado) {
Recurso recurso = repositorioRecurso.buscarPorId(recursoId)
.orElseThrow(RecursoNoExiste::new);
Capitulo capitulo = repositorioCapitulo.buscarPorId(capituloModificado.getId())
.orElseThrow(CapituloNoExiste::new);
capitulo.setNumero(capituloModificado.getNumero());
capitulo.setTitulo(capituloModificado.getTitulo());
capitulo.setTipo(capituloModificado.getTipo());
capitulo.setActivo(capituloModificado.getActivo());
List<FuenteCapitulo> fuentesActuales = new ArrayList<>(capitulo.getFuentes());
List<FuenteCapitulo> fuentesAEliminar = new ArrayList<>();
List<FuenteCapitulo> fuentesNuevas = capituloModificado.getFuentes() != null ? capituloModificado.getFuentes() : new ArrayList<>();
for (FuenteCapitulo fuenteExistente : fuentesActuales) {
boolean sigueExistiendo = capituloModificado.getFuentes().stream()
.anyMatch(f -> f.getNombreFuente().equals(fuenteExistente.getNombreFuente()));
capitulo.getFuentes().removeIf(fuenteExistente ->
fuentesNuevas.stream().noneMatch(f -> f.getNombreFuente().equals(fuenteExistente.getNombreFuente()))
);
if (!sigueExistiendo) {
fuentesAEliminar.add(fuenteExistente);
}
}
for (FuenteCapitulo fuente : fuentesAEliminar) {
repositorioCapitulo.eliminarFuente(fuente);
capitulo.getFuentes().remove(fuente);
}
for (FuenteCapitulo nuevaFuente : capituloModificado.getFuentes()) {
boolean existe = fuentesActuales.stream()
for (FuenteCapitulo nuevaFuente : fuentesNuevas) {
boolean existe = capitulo.getFuentes().stream()
.anyMatch(f -> f.getNombreFuente().equals(nuevaFuente.getNombreFuente()));
if (!existe) {
......@@ -191,42 +275,76 @@ public class ServicioRecursos {
repositorioCapitulo.actualizarCapitulo(capitulo);
}
/**
* @brief Busca un capítulo por su ID.
* @param id Identificador del capítulo.
* @return Capitulo encontrado.
* @throws CapituloNoExiste Si el capítulo no se encuentra en la base de datos.
*/
@Transactional(readOnly = true)
public Capitulo buscarCapituloPorId(Long id) {
Capitulo capitulo = repositorioCapitulo.buscarPorId(id);
if (capitulo == null) {
throw new CapituloNoExiste();
}
return capitulo;
return repositorioCapitulo.buscarPorId(id)
.orElseThrow(CapituloNoExiste::new);
}
/**
* @brief Actualiza la información de una fuente de un capítulo.
* @param fuente Objeto FuenteCapitulo con los datos actualizados.
* @throws IllegalArgumentException Si la fuente no existe en la base de datos.
*/
@Transactional
public void actualizarFuente(FuenteCapitulo fuente) {
FuenteCapitulo fuenteExistente = repositorioCapitulo.buscarFuentePorId(fuente.getId());
if (fuenteExistente != null) {
FuenteCapitulo fuenteExistente = repositorioCapitulo.buscarFuentePorId(fuente.getId())
.orElseThrow(FuenteNoExiste::new);
fuenteExistente.setUrlFuente(fuente.getUrlFuente());
repositorioCapitulo.actualizarFuente(fuenteExistente);
}
}
/**
* @brief Elimina una fuente de un capítulo por su ID.
* @param id Identificador de la fuente a eliminar.
* Si la fuente existe, se elimina; en caso contrario, no realiza ninguna acción.
*/
@Transactional
public void eliminarFuentePorId(Long id) {
FuenteCapitulo fuente = repositorioCapitulo.buscarFuentePorId(id);
if (fuente != null) {
repositorioCapitulo.eliminarFuentePorId(id);
}
repositorioCapitulo.buscarFuentePorId(id)
.ifPresent(fuente -> repositorioCapitulo.eliminarFuentePorId(id));
}
/**
* @brief Agrega una nueva fuente a un capítulo.
* @param fuente Objeto FuenteCapitulo con la información de la nueva fuente.
* @throws IllegalArgumentException Si la fuente o su capítulo son nulos.
*/
@Transactional
public void agregarFuente(FuenteCapitulo fuente) {
if (fuente == null || fuente.getCapitulo() == null) {
throw new IllegalArgumentException("La fuente y su capítulo no pueden ser nulos.");
}
repositorioCapitulo.agregarFuente(fuente);
}
/**
* @brief Elimina una fuente de un capítulo por su ID.
* @param id Identificador de la fuente a eliminar.
* @throws IllegalArgumentException Si la fuente no existe en la base de datos.
*/
@Transactional
public void eliminarFuente(Long id) {
FuenteCapitulo fuente = repositorioCapitulo.buscarFuentePorId(id);
if (fuente != null) {
repositorioCapitulo.eliminarFuentePorId(id);
}
repositorioCapitulo.buscarFuentePorId(id)
.ifPresentOrElse(
fuente -> repositorioCapitulo.eliminarFuentePorId(id),
() -> { throw new FuenteNoExiste(); }
);
}
/**
* @brief Verifica si un recurso existe en la base de datos.
* @param id Identificador del recurso a buscar.
* @return true si el recurso existe, false si no.
*/
public boolean existeRecurso(Long id) {
return repositorioRecurso.buscarPorId(id).isPresent();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment