package de.rwth.idsg.bikeman.psinterface.repository;
import de.rwth.idsg.bikeman.domain.OperationState;
import de.rwth.idsg.bikeman.psinterface.dto.request.ChargingStatusDTO;
import de.rwth.idsg.bikeman.psinterface.dto.request.PedelecStatusDTO;
import de.rwth.idsg.bikeman.web.rest.exception.DatabaseException;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.LocalDateTime;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.Date;
import java.util.List;
/**
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
* @since 16.06.2015
*/
@Repository
@Slf4j
public class PsiPedelecRepositoryImpl implements PsiPedelecRepository {
@PersistenceContext private EntityManager em;
// nachfolgende funktion nur mit einem rückgabewert (keine liste)
@Override
@Transactional(readOnly = true)
public List<String> findAvailablePedelecs(String stationManufacturerId) {
// final String q = "select p.manufacturerId " +
// "from Pedelec p " +
// "join p.chargingStatus cs " +
// "join p.stationSlot ss " +
// "join ss.station s " +
// "left join p.reservations r on (p = r.pedelec " +
// "and not r.state = de.rwth.idsg.bikeman.domain.ReservationState.USED " +
// "and (CURRENT_TIMESTAMP between r.startDateTime and r.endDateTime)) " +
// "where s.manufacturerId = :stationManufacturerId " +
// "and ss.state = de.rwth.idsg.bikeman.domain.OperationState.OPERATIVE " +
// "and p.state = de.rwth.idsg.bikeman.domain.OperationState.OPERATIVE " +
// "and r.pedelec IS NULL " +
// "order by cs.batteryStateOfCharge desc";
final String q = "select p.manufacturerId " +
"from Pedelec p " +
"join p.chargingStatus cs " +
"join p.stationSlot sl " +
"join sl.station s " +
"where s.manufacturerId = :stationManufacturerId " +
"and sl.state = de.rwth.idsg.bikeman.domain.OperationState.OPERATIVE " +
"and p.state = de.rwth.idsg.bikeman.domain.OperationState.OPERATIVE " +
"and p not in (select r.pedelec from Reservation r " +
"where r.state = de.rwth.idsg.bikeman.domain.ReservationState.CREATED " +
"and (:now between r.startDateTime and r.endDateTime)) " +
"order by cs.batteryStateOfCharge desc";
try {
return em.createQuery(q, String.class)
.setParameter("stationManufacturerId", stationManufacturerId)
.setParameter("now", new LocalDateTime())
.setMaxResults(5)
.getResultList();
} catch (Exception e) {
throw new DatabaseException("Failed to find pedelecs in station with manufacturerId "
+ stationManufacturerId, e);
}
}
@Override
@Transactional(readOnly = true)
public List<String> findReservedPedelecs(String stationManufacturerId, String cardId) {
final String q = "SELECT p.manufacturerId " +
"FROM Reservation r " +
"JOIN r.pedelec p " +
"JOIN r.cardAccount ca " +
"JOIN p.stationSlot ss " +
"JOIN ss.station s " +
"WHERE ca.cardId = :cardId " +
"AND (:now BETWEEN r.startDateTime AND r.endDateTime) " +
"AND s.manufacturerId = :stationManufacturerId " +
"AND ss.state = de.rwth.idsg.bikeman.domain.OperationState.OPERATIVE " +
"AND p.state = de.rwth.idsg.bikeman.domain.OperationState.OPERATIVE " +
"AND r.state = de.rwth.idsg.bikeman.domain.ReservationState.CREATED";
try {
return em.createQuery(q, String.class)
.setParameter("stationManufacturerId", stationManufacturerId)
.setParameter("cardId", cardId)
.setParameter("now", new LocalDateTime())
.setMaxResults(1)
.getResultList();
} catch (Exception e) {
throw new DatabaseException("Failed to find pedelecs in station with manufacturerId "
+ stationManufacturerId, e);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updatePedelecStatus(PedelecStatusDTO dto) {
final String s = "UPDATE Pedelec p SET " +
"p.errorCode = :pedelecErrorCode, " +
"p.errorInfo = :pedelecErrorInfo, " +
"p.state = :pedelecState, " +
"p.updated = :updated " +
"WHERE p.manufacturerId = :pedelecManufacturerId";
try {
int count = em.createQuery(s)
.setParameter("pedelecErrorCode", dto.getPedelecErrorCode())
.setParameter("pedelecErrorInfo", dto.getPedelecErrorInfo())
.setParameter("pedelecState", OperationState.valueOf(dto.getPedelecState().name()))
.setParameter("updated", new Date(dto.getTimestamp().getMillis()))
.setParameter("pedelecManufacturerId", dto.getPedelecManufacturerId())
.executeUpdate();
if (count != 1) {
log.warn("Failed to update status of pedelec with manufacturerId {}", dto.getPedelecManufacturerId());
}
} catch (Exception e) {
throw new DatabaseException("Failed to update the pedelec status with manufacturerId "
+ dto.getPedelecManufacturerId(), e);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updatePedelecChargingStatus(List<ChargingStatusDTO> dtoList) {
final String s = "UPDATE PedelecChargingStatus s SET " +
"s.state = :state, " +
"s.meterValue = :meterValue, " +
"s.batteryCycleCount = :cycleCount, " +
"s.batteryStateOfCharge = :stateOfCharge, " +
"s.batteryTemperature = :temperature, " +
"s.batteryVoltage = :voltage, " +
"s.batteryCurrent = :current, " +
"s.timestamp = :timestamp " +
"WHERE s.pedelec = (SELECT p FROM Pedelec p WHERE p.manufacturerId = :pedelecManufacturerId)";
try {
for (ChargingStatusDTO dto : dtoList) {
int count = em.createQuery(s)
.setParameter("state", dto.getChargingState())
.setParameter("meterValue", dto.getMeterValue())
.setParameter("cycleCount", dto.getBattery().getCycleCount())
.setParameter("stateOfCharge", dto.getBattery().getSoc())
.setParameter("temperature", dto.getBattery().getTemperature())
.setParameter("voltage", dto.getBattery().getVoltage())
.setParameter("current", dto.getBattery().getCurrent())
.setParameter("timestamp", dto.getTimestamp().toLocalDateTime())
.setParameter("pedelecManufacturerId", dto.getPedelecManufacturerId())
.executeUpdate();
if (count != 1) {
log.warn("Failed to update charging status of pedelec with manufacturerId {}", dto.getPedelecManufacturerId());
}
}
} catch (Exception e) {
throw new DatabaseException("Failed to update the charging status.", e);
}
}
}