
be.raildelays.repository.impl.LineStopDaoCustomJpa Maven / Gradle / Ivy
The newest version!
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Almex
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
package be.raildelays.repository.impl;
import be.raildelays.domain.entities.LineStop;
import be.raildelays.domain.entities.LineStop_;
import be.raildelays.domain.entities.Station;
import be.raildelays.domain.entities.TrainLine;
import be.raildelays.repository.LineStopDaoCustom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.domain.Specifications;
import org.springframework.data.jpa.repository.query.QueryUtils;
import org.springframework.util.Assert;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import static be.raildelays.repository.specification.LineStopSpecifications.*;
import static org.springframework.data.jpa.domain.Specifications.where;
@SuppressWarnings("unused") // Injected via Spring Data JPA
public class LineStopDaoCustomJpa implements LineStopDaoCustom {
private static final Logger LOGGER = LoggerFactory.getLogger(LineStopDaoCustomJpa.class);
@PersistenceContext
@SuppressWarnings("unused") // Injected via CDI
private EntityManager entityManager;
@Override
public Page findDepartureDelays(LocalDate date, Station station, long delayThreshold, Pageable pageable) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery(LineStop.class);
Subquery canceled = query.subquery(Long.class);
Subquery notCanceled = query.subquery(Long.class);
Root canceledRoot = canceled.from(LineStop.class);
Root notCanceledRoot = notCanceled.from(LineStop.class);
LOGGER.debug("Searching delays for : date={} station={} threshold={}",
date, station, delayThreshold);
canceled.select(canceledRoot.get(LineStop_.id))
.where(where(dateEquals(date))
.and(stationEquals(station))
.and(isCanceledDeparture())
.toPredicate(canceledRoot, query, builder));
notCanceled.select(notCanceledRoot.get(LineStop_.id))
.where(where(dateEquals(date))
.and(stationEquals(station))
.and(departureDelayIsNotNull())
.and(departureDelayGreaterThanOrEqualTo(delayThreshold))
.toPredicate(notCanceledRoot, query, builder));
Page all = findAll(where(idsIn(canceled)).or(idsIn(notCanceled)), pageable);
LOGGER.debug("Retrieved delays : size={}/{} elements={}/{} pages={}/{}",
all.getContent().size(), all.getSize(),
all.getNumberOfElements(), all.getTotalElements(),
all.getNumber(), all.getTotalPages());
return all;
}
@Override
public List findDepartureDelays(LocalDate date, Station station, long delayThreshold) {
return findDepartureDelays(date, station, delayThreshold, null).getContent();
}
@Override
public Page findArrivalDelays(LocalDate date, Station station, long delayThreshold, Pageable pageable) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery(LineStop.class);
Subquery canceled = query.subquery(Long.class);
Subquery notCanceled = query.subquery(Long.class);
Root canceledRoot = canceled.from(LineStop.class);
Root notCanceledRoot = notCanceled.from(LineStop.class);
LOGGER.debug("Searching delays for : date={} station={} threshold={}",
date, station, delayThreshold);
canceled.select(canceledRoot.get(LineStop_.id))
.where(where(dateEquals(date))
.and(stationEquals(station))
.and(isCanceledArrival())
.toPredicate(canceledRoot, query, builder));
notCanceled.select(notCanceledRoot.get(LineStop_.id))
.where(where(dateEquals(date))
.and(stationEquals(station))
.and(arrivalDelayIsNotNull())
.and(arrivalDelayGreaterThanOrEqualTo(delayThreshold))
.toPredicate(notCanceledRoot, query, builder));
Page all = findAll(where(idsIn(canceled)).or(idsIn(notCanceled)), pageable);
LOGGER.debug("Retrieved delays : size={}/{} elements={}/{} pages={}/{}",
all.getContent().size(), all.getSize(),
all.getNumberOfElements(), all.getTotalElements(),
all.getNumber(), all.getTotalPages());
return all;
}
@Override
public List findArrivalDelays(LocalDate date, Station station, long delayThreshold) {
return findArrivalDelays(date, station, delayThreshold, null).getContent();
}
@Override
public List findNextExpectedArrivalTime(Station station, LocalDateTime dateTime) {
return findAll(where(dateEquals(dateTime.toLocalDate()))
.and(arrivalTimeIsNotNull())
.and(arrivalTimeGreaterThan(dateTime.toLocalTime()))
.and(stationEquals(station)),
new Sort(Sort.Direction.ASC, "arrivalTime.expectedTime")
);
}
@Override
public LineStop findFistScheduledLine(TrainLine trainLine, Station station) {
return findFirstOne(where(arrivalTimeIsNotNull())
.and(departureTimeIsNotNull())
.and(isNotCanceled())
.and(stationEquals(station))
.and(trainEquals(trainLine)));
}
@Override
public LineStop findByTrainLineAndDateAndStation(TrainLine trainLine, LocalDate date, Station station) {
return findFirstOne(where(dateEquals(date))
.and(stationEquals(station))
.and(trainEquals(trainLine)));
}
private Page findAll(Specifications specifications, Pageable pageable) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery(LineStop.class);
Root root = query.from(LineStop.class);
query = query.where(specifications.toPredicate(root, query, builder));
if (pageable != null && pageable.getSort() != null) {
query = query.orderBy(QueryUtils.toOrders(pageable.getSort(), root, builder));
}
TypedQuery typedQuery = entityManager.createQuery(query);
return pageable == null ? new PageImpl<>(typedQuery.getResultList()) : readPage(typedQuery, pageable, specifications);
}
protected Page readPage(TypedQuery query, Pageable pageable, Specification specifications) {
query.setFirstResult(pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
Long total = executeCountQuery(getCountQuery(specifications));
List content = total > pageable.getOffset() ? query.getResultList() : Collections.emptyList();
return new PageImpl<>(content, pageable, total);
}
private static Long executeCountQuery(TypedQuery query) {
Assert.notNull(query);
List totals = query.getResultList();
Long total = 0L;
for (Long element : totals) {
total += element == null ? 0 : element;
}
return total;
}
private List findAll(Specifications specifications, Sort sort) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery(LineStop.class);
Root root = query.from(LineStop.class);
return entityManager
.createQuery(query
.where(specifications.toPredicate(root, query, builder))
.orderBy(QueryUtils.toOrders(sort, root, builder))
).getResultList();
}
protected TypedQuery getCountQuery(Specification specification) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery(Long.class);
Root root = applySpecificationToCriteria(specification, query);
if (query.isDistinct()) {
query.select(builder.countDistinct(root));
} else {
query.select(builder.count(root));
}
return entityManager.createQuery(query);
}
private Root applySpecificationToCriteria(Specification specification, CriteriaQuery query) {
Assert.notNull(query);
Root root = query.from(LineStop.class);
if (specification == null) {
return root;
}
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
Predicate predicate = specification.toPredicate(root, query, builder);
if (predicate != null) {
query.where(predicate);
}
return root;
}
private LineStop findFirstOne(Specifications specification) {
LineStop result = null;
try {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery(LineStop.class);
Root root = query.from(LineStop.class);
result = entityManager
.createQuery(query.where(specification.toPredicate(root, query, builder)))
.setMaxResults(1)
.setFirstResult(0)
.getSingleResult();
} catch (NoResultException e) {
LOGGER.trace("We have no result to return.", e);
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy