package org.zalando.catwatch.backend.repo;
import com.mysema.query.BooleanBuilder;
import com.mysema.query.jpa.JPASubQuery;
import com.mysema.query.jpa.impl.JPAQuery;
import com.mysema.query.types.query.DateTimeSubQuery;
import org.zalando.catwatch.backend.model.Project;
import org.zalando.catwatch.backend.model.QProject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
class ProjectRepositoryImpl implements ProjectRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
private final QProject project = QProject.project;
@Override
public List<Project> findProjects(String organization, Optional<String> query, Optional<String> language) {
DateTimeSubQuery<Date> lastSnapshot = new JPASubQuery().from(project)
.where(project.organizationName.eq(organization))
.unique(project.snapshotDate.max());
BooleanBuilder q = new BooleanBuilder()
.and(project.organizationName.eq(organization))
.and(project.snapshotDate.eq(lastSnapshot));
if (query.isPresent()) {
q.and(project.name.startsWith(query.get()));
}
if (language.isPresent()) {
q.and(project.primaryLanguage.eq(language.get()));
}
return queryProject().where(q).list(project);
}
@Override
public List<Project> findProjects(String organization, Date snapshotDate, Optional<String> query, Optional<String> language) {
BooleanBuilder q = new BooleanBuilder(project.organizationName.eq(organization));
Optional<Date> snapshotDateMatch = getSnapshotDateMatch(snapshotDate, organization);
if (!snapshotDateMatch.isPresent()) {
return Collections.emptyList();
}
q.and(project.snapshotDate.eq(snapshotDateMatch.get()));
if (query.isPresent()) {
q.and(project.name.startsWith(query.get()));
}
if (language.isPresent()) {
q.and(project.primaryLanguage.eq(language.get()));
}
return queryProject().where(q).list(project);
}
/**
* @param snapshot
*
* @return date that is closest in the past. If there is no earlier date in
* the past, nothing is returned
*/
private Optional<Date> getSnapshotDateMatch(Date snapshot, String organization) {
return queryProject()
.where(
project.organizationName.eq(organization)
.and(project.snapshotDate.loe(snapshot))
)
.orderBy(project.snapshotDate.desc())
.limit(1)
.list(project)
.stream()
.findFirst()
.map(Project::getSnapshotDate);
}
private JPAQuery queryProject() {
return new JPAQuery(entityManager).from(project);
}
}