Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
32 changes: 32 additions & 0 deletions src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Alerta.java
Original file line number Diff line number Diff line change
@@ -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<String> 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);
}
}

50 changes: 48 additions & 2 deletions src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Clima.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

}
32 changes: 24 additions & 8 deletions src/main/java/ar/utn/ba/ddsi/mailing/models/entities/Email.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import java.util.concurrent.atomic.AtomicLong;

@Repository
public class EmailRepository implements IEmailRepository {
public class
EmailRepository implements IEmailRepository {
private final Map<Long, Email> emails = new HashMap<>();
private final AtomicLong idGenerator = new AtomicLong(1);

Expand Down
Original file line number Diff line number Diff line change
@@ -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<Clima> obtenerClima(String ciudad);
}
Original file line number Diff line number Diff line change
@@ -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<Clima> 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));
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<Void> actualizarClimaCiudades() {
return Flux.fromArray(CIUDADES_ARGENTINA)
.flatMap(this::obtenerClimaDeAPI)
@Override
public Mono<Void> 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<Clima> 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;
});
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -34,7 +38,7 @@ public List<Email> obtenerEmails(Boolean pendiente) {
public void procesarPendientes() {
List<Email> pendientes = emailRepository.findByEnviado(false);
for (Email email : pendientes) {
email.enviar();
emailSender.enviar(email);
email.setEnviado(true);
emailRepository.save(email);
}
Expand Down