video-surveillance-app/src/main/java/me/belkacemi/iotalarm/infrastructure/persistence/AlarmReadModelAdapter.java

87 lines
3.5 KiB
Java
Raw Normal View History

package me.belkacemi.iotalarm.infrastructure.persistence;
import me.belkacemi.iotalarm.application.query.port.AlarmReadModelPort;
import me.belkacemi.iotalarm.application.query.view.AlarmStatusView;
import me.belkacemi.iotalarm.application.query.view.AlertView;
import me.belkacemi.iotalarm.domain.model.AlarmPolicy;
import me.belkacemi.iotalarm.domain.model.AlarmState;
import me.belkacemi.iotalarm.infrastructure.persistence.jpa.AlarmStateJpaRepository;
import me.belkacemi.iotalarm.infrastructure.persistence.jpa.AlertJpaRepository;
import me.belkacemi.iotalarm.infrastructure.persistence.mapper.AlertMapper;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Component;
import java.time.Clock;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
/**
* ADAPTER SORTANT du cote LECTURE : implementation du {@link AlarmReadModelPort}.
*
* <p>Il ne charge jamais l'agregat. Il assemble une vue a partir de requetes
* ciblees - c'est la raison d'etre du CQRS : afficher un compteur d'alertes non
* acquittees via un {@code COUNT(*)} plutot qu'en rehydratant un objet metier
* complet dont on n'utiliserait aucune methode.</p>
*/
@Component
public class AlarmReadModelAdapter implements AlarmReadModelPort {
private final AlertJpaRepository alertRepository;
private final AlarmStateJpaRepository alarmStateRepository;
private final AlarmPolicy policy;
private final Clock clock;
public AlarmReadModelAdapter(AlertJpaRepository alertRepository,
AlarmStateJpaRepository alarmStateRepository,
AlarmPolicy policy,
Clock clock) {
this.alertRepository = alertRepository;
this.alarmStateRepository = alarmStateRepository;
this.policy = policy;
this.clock = clock;
}
@Override
public Optional<AlarmStatusView> alarmStatus(String zoneId) {
long unacknowledged = alertRepository.countByZoneIdAndAcknowledgedFalse(zoneId);
AlertView lastAlert = alertRepository.findFirstByZoneIdOrderByDetectedAtDesc(zoneId)
.map(AlertMapper::toView)
.orElse(null);
return Optional.of(alarmStateRepository.findById(zoneId)
.map(entity -> new AlarmStatusView(
entity.getZoneId(),
entity.getState().name(),
entity.getStateChangedAt(),
policy.exitDelay().toSeconds(),
entity.getLastAlertAt(),
unacknowledged,
lastAlert))
// Base neuve : l'alarme n'a simplement jamais ete armee. La
// console doit afficher DESARMEE, pas une erreur 404.
.orElseGet(() -> new AlarmStatusView(
zoneId,
AlarmState.DISARMED.name(),
clock.instant(),
policy.exitDelay().toSeconds(),
null,
unacknowledged,
lastAlert)));
}
@Override
public List<AlertView> recentAlerts(String zoneId, int limit) {
return alertRepository
.findByZoneIdOrderByDetectedAtDesc(zoneId, PageRequest.of(0, limit))
.stream()
.map(AlertMapper::toView)
.toList();
}
@Override
public Optional<AlertView> findAlert(UUID alertId) {
return alertRepository.findById(alertId).map(AlertMapper::toView);
}
}