diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/components/WeatherResponseMapper.java b/src/main/java/ar/utn/ba/ddsi/mailing/components/WeatherResponseMapper.java new file mode 100644 index 0000000..b529ed8 --- /dev/null +++ b/src/main/java/ar/utn/ba/ddsi/mailing/components/WeatherResponseMapper.java @@ -0,0 +1,21 @@ +package ar.utn.ba.ddsi.mailing.components; + +import ar.utn.ba.ddsi.mailing.models.dto.external.weatherapi.WeatherResponse; +import ar.utn.ba.ddsi.mailing.models.entities.Clima; +import org.springframework.stereotype.Component; + +@Component +public class WeatherResponseMapper { + public Clima map(String ciudad, WeatherResponse response) { + Clima clima = new Clima(); + clima.setCiudad(ciudad); + clima.setRegion(response.getLocation().getRegion()); + clima.setPais(response.getLocation().getCountry()); + clima.setTemperaturaCelsius(response.getCurrent().getTemp_c()); + clima.setTemperaturaFahrenheit(response.getCurrent().getTemp_f()); + clima.setCondicion(response.getCurrent().getCondition().getText()); + clima.setVelocidadVientoKmh(response.getCurrent().getWind_kph()); + clima.setHumedad(response.getCurrent().getHumidity()); + return clima; + } +} \ No newline at end of file diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/models/adapters/IEmailAdapterSender.java b/src/main/java/ar/utn/ba/ddsi/mailing/models/adapters/IEmailAdapterSender.java new file mode 100644 index 0000000..fd94620 --- /dev/null +++ b/src/main/java/ar/utn/ba/ddsi/mailing/models/adapters/IEmailAdapterSender.java @@ -0,0 +1,7 @@ +package ar.utn.ba.ddsi.mailing.models.adapters; + +import ar.utn.ba.ddsi.mailing.models.entities.Email; + +public interface IEmailAdapterSender { + void enviar(Email email); +} diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/models/adapters/impl/EmailSenderA.java b/src/main/java/ar/utn/ba/ddsi/mailing/models/adapters/impl/EmailSenderA.java new file mode 100644 index 0000000..14db3d0 --- /dev/null +++ b/src/main/java/ar/utn/ba/ddsi/mailing/models/adapters/impl/EmailSenderA.java @@ -0,0 +1,12 @@ +package ar.utn.ba.ddsi.mailing.models.adapters.impl; + +import ar.utn.ba.ddsi.mailing.models.adapters.IEmailAdapterSender; +import ar.utn.ba.ddsi.mailing.models.entities.Email; + +public class EmailSenderA implements IEmailAdapterSender { + + @Override + public void enviar(Email email) { + System.out.println("Enviando email a " + email.getDestinatario()); + } +} \ No newline at end of file diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Alerta.java b/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Alerta.java new file mode 100644 index 0000000..e1ec0ef --- /dev/null +++ b/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Alerta.java @@ -0,0 +1,32 @@ +package ar.utn.ba.ddsi.mailing.models.entities; + +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@Setter +@Getter +public class Alerta { + private List CiudadesArgentina; + private double Temperatura; + private int Humedad; + + + public Alerta() { + this.CiudadesArgentina = new ArrayList<>(List.of( + "Buenos Aires", "Cordoba", "Rosario", "Mendoza", "Tucuman", + "La Plata", "Mar del Plata", "Salta", "Santa Fe", "San Juan" + )); + } + + public void agregarCiudad(String ciudad) { + CiudadesArgentina.add(ciudad); + } + + public void quitarCiudad(String ciudad) { + CiudadesArgentina.remove(ciudad); + } +} + diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Clima.java b/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Clima.java index 4eaa65b..58b94c6 100644 --- a/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Clima.java +++ b/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Clima.java @@ -4,23 +4,69 @@ import lombok.Setter; import java.time.LocalDateTime; -@Getter -@Setter + public class Clima { + @Getter + @Setter private Long id; + @Getter + @Setter private String ciudad; + @Getter + @Setter private String region; + @Getter + @Setter private String pais; + @Getter private Double temperaturaCelsius; private Double temperaturaFahrenheit; + @Getter + @Setter private String condicion; + @Getter + @Setter private Double velocidadVientoKmh; + @Getter + @Setter private Integer humedad; + @Getter + @Setter private LocalDateTime fechaActualizacion; + @Getter + @Setter private boolean procesado; public Clima() { this.fechaActualizacion = LocalDateTime.now(); this.procesado = false; } + + public void setTemperaturaCelsius(Double temperaturaCelsius) { + this.temperaturaCelsius = temperaturaCelsius; + this.fechaActualizacion = LocalDateTime.now(); + } + + public Double getTemperaturaFahrenheit() { + if (temperaturaCelsius == null) return null; + return temperaturaCelsius * 9 / 5 + 32; + } + + public void setTemperaturaFahrenheit(Double temperaturaFahrenheit) { + if (temperaturaFahrenheit != null) { + this.temperaturaCelsius = (temperaturaFahrenheit - 32) * 5 / 9; + this.fechaActualizacion = LocalDateTime.now(); + } + } + + public void actualizarDatos(Double nuevaTemperaturaCelsius, String nuevaCondicion, + Double nuevaVelocidadVientoKmh, Integer nuevaHumedad) { + setTemperaturaCelsius(nuevaTemperaturaCelsius); + this.condicion = nuevaCondicion; + this.velocidadVientoKmh = nuevaVelocidadVientoKmh; + this.humedad = nuevaHumedad; + this.fechaActualizacion = LocalDateTime.now(); + this.procesado = false; + } + } \ No newline at end of file diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Email.java b/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Email.java index eb940be..d965f0d 100644 --- a/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Email.java +++ b/src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Email.java @@ -1,19 +1,32 @@ package ar.utn.ba.ddsi.mailing.models.entities; +import ar.utn.ba.ddsi.mailing.models.adapters.IEmailAdapterSender; import lombok.Getter; import lombok.Setter; -@Setter +import java.util.Objects; +import java.util.concurrent.atomic.AtomicLong; + @Getter +@Setter public class Email { - private Long id; - private String destinatario; - private String remitente; - private String asunto; - private String contenido; + private final Long id; + private final String destinatario; + private final String remitente; + private final String asunto; + private final String contenido; private boolean enviado; + private static final AtomicLong contadorIds = new AtomicLong(0); + private IEmailAdapterSender emailSender; + public Email(String destinatario, String remitente, String asunto, String contenido) { + Objects.requireNonNull(destinatario, "El destinatario no puede ser null"); + Objects.requireNonNull(remitente, "El remitente no puede ser null"); + if (destinatario.isBlank()) throw new IllegalArgumentException("El destinatario no puede estar vacio"); + if (remitente.isBlank()) throw new IllegalArgumentException("El remitente no puede estar vacio"); + + this.id = contadorIds.incrementAndGet(); this.destinatario = destinatario; this.remitente = remitente; this.asunto = asunto; @@ -22,6 +35,9 @@ public Email(String destinatario, String remitente, String asunto, String conten } public void enviar() { - //TODO: Implementación pendiente. Podríamos usar adapters + if (!enviado) { + emailSender.enviar(this); + this.enviado = true; + } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/models/repositories/impl/EmailRepository.java b/src/main/java/ar/utn/ba/ddsi/mailing/models/repositories/impl/EmailRepository.java index 2920146..4b1de33 100644 --- a/src/main/java/ar/utn/ba/ddsi/mailing/models/repositories/impl/EmailRepository.java +++ b/src/main/java/ar/utn/ba/ddsi/mailing/models/repositories/impl/EmailRepository.java @@ -7,7 +7,8 @@ import java.util.concurrent.atomic.AtomicLong; @Repository -public class EmailRepository implements IEmailRepository { +public class +EmailRepository implements IEmailRepository { private final Map emails = new HashMap<>(); private final AtomicLong idGenerator = new AtomicLong(1); diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/services/IClimaProvider.java b/src/main/java/ar/utn/ba/ddsi/mailing/services/IClimaProvider.java new file mode 100644 index 0000000..6d755ae --- /dev/null +++ b/src/main/java/ar/utn/ba/ddsi/mailing/services/IClimaProvider.java @@ -0,0 +1,8 @@ +package ar.utn.ba.ddsi.mailing.services; + +import ar.utn.ba.ddsi.mailing.models.entities.Clima; +import reactor.core.publisher.Mono; + +public interface IClimaProvider { + Mono obtenerClima(String ciudad); +} diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/ClimaProviderAPI.java b/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/ClimaProviderAPI.java new file mode 100644 index 0000000..fef04ee --- /dev/null +++ b/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/ClimaProviderAPI.java @@ -0,0 +1,42 @@ +package ar.utn.ba.ddsi.mailing.services.impl; + +import ar.utn.ba.ddsi.mailing.components.WeatherResponseMapper; +import ar.utn.ba.ddsi.mailing.models.dto.external.weatherapi.WeatherResponse; +import ar.utn.ba.ddsi.mailing.models.entities.Clima; +import ar.utn.ba.ddsi.mailing.services.IClimaProvider; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +@Service +public class ClimaProviderAPI implements IClimaProvider { + + private final WebClient webClient; + private final String apiKey; + private final WeatherResponseMapper mapper; + + public ClimaProviderAPI( + @Value("${weather.api.key}") String apiKey, + @Value("${weather.api.base-url}") String baseUrl, + WeatherResponseMapper mapper + ) { + this.apiKey = apiKey; + this.webClient = WebClient.builder().baseUrl(baseUrl).build(); + this.mapper = mapper; + } + + @Override + public Mono obtenerClima(String ciudad) { + return webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/current.json") + .queryParam("key", apiKey) + .queryParam("q", ciudad) + .queryParam("aqi", "no") + .build()) + .retrieve() + .bodyToMono(WeatherResponse.class) + .map(response -> mapper.map(ciudad, response)); + } +} diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/ClimaService.java b/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/ClimaService.java index d2296b4..017cfed 100644 --- a/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/ClimaService.java +++ b/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/ClimaService.java @@ -1,8 +1,10 @@ package ar.utn.ba.ddsi.mailing.services.impl; +import ar.utn.ba.ddsi.mailing.models.entities.Alerta; import ar.utn.ba.ddsi.mailing.models.entities.Clima; import ar.utn.ba.ddsi.mailing.models.repositories.IClimaRepository; import ar.utn.ba.ddsi.mailing.models.dto.external.weatherapi.WeatherResponse; +import ar.utn.ba.ddsi.mailing.services.IClimaProvider; import ar.utn.ba.ddsi.mailing.services.IClimaService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,66 +14,37 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; + @Service public class ClimaService implements IClimaService { - private static final Logger logger = LoggerFactory.getLogger(ClimaService.class); - private static final String[] CIUDADES_ARGENTINA = { - "Buenos Aires", "Cordoba", "Rosario", "Mendoza", "Tucuman", - "La Plata", "Mar del Plata", "Salta", "Santa Fe", "San Juan" - }; + private static final Logger logger = LoggerFactory.getLogger(ClimaService.class); - private final IClimaRepository climaRepository; - private final WebClient webClient; - private final String apiKey; + private final IClimaRepository climaRepository; + private final IClimaProvider climaProvider; + private final Alerta alerta; - public ClimaService( - IClimaRepository climaRepository, - @Value("${weather.api.key}") String apiKey, - @Value("${weather.api.base-url}") String baseUrl) { - this.climaRepository = climaRepository; - this.apiKey = apiKey; - this.webClient = WebClient.builder() - .baseUrl(baseUrl) - .build(); - } + public ClimaService( + IClimaRepository climaRepository, + IClimaProvider climaProvider + ) { + this.climaRepository = climaRepository; + this.climaProvider = climaProvider; + this.alerta = new Alerta(); + } - @Override - public Mono actualizarClimaCiudades() { - return Flux.fromArray(CIUDADES_ARGENTINA) - .flatMap(this::obtenerClimaDeAPI) + @Override + public Mono actualizarClimaCiudades() { + return Flux.fromIterable(alerta.getCiudadesArgentina()) + .flatMap(climaProvider::obtenerClima) .flatMap(clima -> { - climaRepository.save(clima); - logger.info("Clima actualizado para: {}", clima.getCiudad()); - return Mono.empty(); + climaRepository.save(clima); + logger.info("Clima actualizado para: {}", clima.getCiudad()); + return Mono.empty(); }) .onErrorResume(e -> { - logger.error("Error al actualizar el clima: {}", e.getMessage()); - return Mono.empty(); + logger.error("Error al actualizar el clima: {}", e.getMessage()); + return Mono.empty(); }) .then(); - } - - private Mono obtenerClimaDeAPI(String ciudad) { - return webClient.get() - .uri(uriBuilder -> uriBuilder - .path("/current.json") - .queryParam("key", apiKey) - .queryParam("q", ciudad) - .queryParam("aqi", "no") - .build()) - .retrieve() - .bodyToMono(WeatherResponse.class) - .map(response -> { - Clima clima = new Clima(); - clima.setCiudad(ciudad); - clima.setRegion(response.getLocation().getRegion()); - clima.setPais(response.getLocation().getCountry()); - clima.setTemperaturaCelsius(response.getCurrent().getTemp_c()); - clima.setTemperaturaFahrenheit(response.getCurrent().getTemp_f()); - clima.setCondicion(response.getCurrent().getCondition().getText()); - clima.setVelocidadVientoKmh(response.getCurrent().getWind_kph()); - clima.setHumedad(response.getCurrent().getHumidity()); - return clima; - }); - } -} \ No newline at end of file + } +} diff --git a/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/EmailService.java b/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/EmailService.java index e1ffb85..51a8633 100644 --- a/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/EmailService.java +++ b/src/main/java/ar/utn/ba/ddsi/mailing/services/impl/EmailService.java @@ -1,17 +1,21 @@ package ar.utn.ba.ddsi.mailing.services.impl; +import ar.utn.ba.ddsi.mailing.models.adapters.IEmailAdapterSender; +import ar.utn.ba.ddsi.mailing.models.adapters.impl.EmailSenderA; import ar.utn.ba.ddsi.mailing.models.entities.Email; import ar.utn.ba.ddsi.mailing.models.repositories.IEmailRepository; import ar.utn.ba.ddsi.mailing.services.IEmailService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; + import java.util.List; @Service public class EmailService implements IEmailService { private static final Logger logger = LoggerFactory.getLogger(EmailService.class); private final IEmailRepository emailRepository; + private IEmailAdapterSender emailSender; public EmailService(IEmailRepository emailRepository) { this.emailRepository = emailRepository; @@ -34,7 +38,7 @@ public List obtenerEmails(Boolean pendiente) { public void procesarPendientes() { List pendientes = emailRepository.findByEnviado(false); for (Email email : pendientes) { - email.enviar(); + emailSender.enviar(email); email.setEnviado(true); emailRepository.save(email); }