PostRepository.java
package model.repository;
import model.entity.Post;
import model.entity.Section;
import model.entity.User;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Classe che incapsula la logica per il recupero di entità di tipo {@link Post}
*/
public class PostRepository implements Serializable {
@PersistenceContext
protected EntityManager em;
/**
* Restituisce una nuova istanza di PostFinder
* @return nuova istanza di PostFinder
*/
public PostFinder getFinder(){
return new PostFinder();
}
private enum SortCriteria {OLDEST, NEWEST, MOSTVOTED};
/**
* Classe interna usata per specificare i parametri di ricerca di un post
*/
public class PostFinder {
private User author;
private List<Section> sections;
private Instant before;
private Instant after;
private int offset = 0;
private int pageSize = 30;
private String content;
private boolean includeBody = false;
private User joinUserFollows;
private SortCriteria sortCriteria = PostRepository.SortCriteria.NEWEST;
protected PostFinder(){ }
/**
* Setta il campo author e restituisce l'istanza passata di PostFinder
* @param author entità User dell'autore dei post
* @return istanza passata di PostFinder
*/
public PostFinder byAuthor(User author){
this.author = author;
return this;
}
/**
* Setta il campo content e restituisce l'istanza passata di PostFinder
* @param author text contenuto dei post
* @return istanza passata di PostFinder
*/
public PostFinder byContent(String text){
this.content = text;
return this;
}
/**
* Setta il campo sections e restituisce l'istanza passata di PostFinder
* @param sections lista di sezioni
* @return istanza passata di PostFinder
*/
public PostFinder bySections(List<Section> sections){
this.sections = sections;
return this;
}
/**
* Setta il campo sections e restituisce l'istanza passata di PostFinder
* @param sections sezione dei post
* @return istanza passata di PostFinder
*/
public PostFinder bySection(Section section){
this.sections = Collections.singletonList(section);
return this;
}
/**
* Setta il campo postedAfter e restituisce l'istanza passata di PostFinder
* @param after data dopo la quale i post da trovare sono stati postati
* @return istanza passata di PostFinder
*/
public PostFinder postedAfter(Instant after){
this.after = after;
return this;
}
/**
* Setta il campo postedBefore e restituisce l'istanza passata di PostFinder
* @param before data prima della quale i post da trovare sono stati postati
* @return istanza passata di PostFinder
*/
public PostFinder postedBefore(Instant before){
this.before = before;
return this;
}
/**
* Setta il campo offset e restituisce l'istanza passata di PostFinder
* @param n offset per la paginazione
* @return istanza passata di PostFinder
*/
public PostFinder offset(int n){
offset = n;
return this;
}
/**
* Setta il campo limit e restituisce l'istanza passata di PostFinder
* @param n limite di post da caricare
* @return istanza passata di PostFinder
*/
public PostFinder limit(int n){
pageSize = n;
return this;
}
/**
* Setta il campo sortCriteria a oldest e restituisce l'istanza passata di PostFinder
* @return istanza passata di PostFinder
*/
public PostFinder getOldest(){
sortCriteria = SortCriteria.OLDEST;
return this;
}
/**
* Setta il campo sortCriteria a newest e restituisce l'istanza passata di PostFinder
* @return istanza passata di PostFinder
*/
public PostFinder getNewest(){
sortCriteria = SortCriteria.NEWEST;
return this;
}
/**
* Setta il campo sortCriteria a most voted e restituisce l'istanza passata di PostFinder
* @return istanza passata di PostFinder
*/
public PostFinder getMostVoted(){
sortCriteria = SortCriteria.MOSTVOTED;
return this;
}
/**
* Setta il campo includeBody a true e restituisce l'istanza passata di PostFinder
* @return istanza passata di PostFinder
*/
public PostFinder includeBody(){
includeBody = true;
return this;
}
/**
* Setta il campo joinUserFollows e restituisce l'istanza passata di PostFinder
* @param user entita utente da cui ottenere le sezioni seguite
* @return istanza passata di PostFinder
*/
public PostFinder joinUserFollows(User user){
joinUserFollows = user;
return this;
}
/**
* Restituisce tutti i post che rispettano i criteri di ricerca
* @return lista di entità Post
*/
public List<Post> getResults(){
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Post> cq = cb.createQuery(Post.class);
Root<Post> root = cq.from(Post.class);
List<Predicate> predicates = new ArrayList<>();
if(author != null) {
predicates.add(cb.equal(root.get("author"), author));
}
if(sections != null && !sections.isEmpty()) {
predicates.add(root.get("section").in(sections));
}
if(after != null) {
predicates.add(cb.greaterThanOrEqualTo(root.get("creationDate"), after));
}
if(before != null) {
predicates.add(cb.lessThanOrEqualTo(root.get("creationDate"), before));
}
if(content != null) {
if(includeBody) {
predicates.add(
cb.or(
cb.like(root.get("title"), '%' + content + '%'),
cb.and(
cb.notEqual(root.get("type"), Post.Type.IMG),
cb.like(root.get("content"), '%' + content + '%')
)));
} else {
predicates.add(cb.like(root.get("title"), '%' + content + '%'));
}
}
if(joinUserFollows != null){
Join<Object, Object> joinFollow = root.join("section").join("follows");
predicates.add(cb.equal(joinFollow.get("user"), joinUserFollows));
}
cq.where(cb.and(predicates.toArray(Predicate[]::new)));
switch (sortCriteria) {
case MOSTVOTED:
cq.orderBy(cb.desc(root.get("votesCount")));
break;
case OLDEST:
cq.orderBy(cb.asc(root.get("creationDate")));
break;
case NEWEST:
default:
cq.orderBy(cb.desc(root.get("creationDate")));
break;
}
TypedQuery<Post> tq = em.createQuery(cq);
if(offset >= 0)
tq.setFirstResult(offset);
if(pageSize>=0)
tq.setMaxResults(pageSize);
return tq.getResultList();
}
}
}