1 package model.repository;
2
3 import model.entity.Post;
4 import model.entity.Section;
5 import model.entity.User;
6
7 import javax.persistence.EntityManager;
8 import javax.persistence.PersistenceContext;
9 import javax.persistence.TypedQuery;
10 import javax.persistence.criteria.*;
11 import java.io.Serializable;
12 import java.time.Instant;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16
17
18
19
20 public class PostRepository implements Serializable {
21
22 @PersistenceContext
23 protected EntityManager em;
24
25
26
27
28
29 public PostFinder getFinder(){
30 return new PostFinder();
31 }
32
33 private enum SortCriteria {OLDEST, NEWEST, MOSTVOTED};
34
35
36
37
38 public class PostFinder {
39 private User author;
40 private List<Section> sections;
41 private Instant before;
42 private Instant after;
43 private int offset = 0;
44 private int pageSize = 30;
45 private String content;
46 private boolean includeBody = false;
47 private User joinUserFollows;
48 private SortCriteria sortCriteria = PostRepository.SortCriteria.NEWEST;
49
50 protected PostFinder(){ }
51
52
53
54
55
56
57 public PostFinder byAuthor(User author){
58 this.author = author;
59 return this;
60 }
61
62
63
64
65
66
67 public PostFinder byContent(String text){
68 this.content = text;
69 return this;
70 }
71
72
73
74
75
76
77 public PostFinder bySections(List<Section> sections){
78 this.sections = sections;
79 return this;
80 }
81
82
83
84
85
86
87 public PostFinder bySection(Section section){
88 this.sections = Collections.singletonList(section);
89 return this;
90 }
91
92
93
94
95
96
97 public PostFinder postedAfter(Instant after){
98 this.after = after;
99 return this;
100 }
101
102
103
104
105
106
107 public PostFinder postedBefore(Instant before){
108 this.before = before;
109 return this;
110 }
111
112
113
114
115
116
117 public PostFinder offset(int n){
118 offset = n;
119 return this;
120 }
121
122
123
124
125
126
127 public PostFinder limit(int n){
128 pageSize = n;
129 return this;
130 }
131
132
133
134
135
136 public PostFinder getOldest(){
137 sortCriteria = SortCriteria.OLDEST;
138 return this;
139 }
140
141
142
143
144
145 public PostFinder getNewest(){
146 sortCriteria = SortCriteria.NEWEST;
147 return this;
148 }
149
150
151
152
153
154 public PostFinder getMostVoted(){
155 sortCriteria = SortCriteria.MOSTVOTED;
156 return this;
157 }
158
159
160
161
162
163 public PostFinder includeBody(){
164 includeBody = true;
165 return this;
166 }
167
168
169
170
171
172
173 public PostFinder joinUserFollows(User user){
174 joinUserFollows = user;
175 return this;
176 }
177
178
179
180
181
182 public List<Post> getResults(){
183 CriteriaBuilder cb = em.getCriteriaBuilder();
184 CriteriaQuery<Post> cq = cb.createQuery(Post.class);
185 Root<Post> root = cq.from(Post.class);
186
187 List<Predicate> predicates = new ArrayList<>();
188
189 if(author != null) {
190 predicates.add(cb.equal(root.get("author"), author));
191 }
192
193 if(sections != null && !sections.isEmpty()) {
194 predicates.add(root.get("section").in(sections));
195 }
196
197 if(after != null) {
198 predicates.add(cb.greaterThanOrEqualTo(root.get("creationDate"), after));
199 }
200
201 if(before != null) {
202 predicates.add(cb.lessThanOrEqualTo(root.get("creationDate"), before));
203 }
204
205 if(content != null) {
206 if(includeBody) {
207 predicates.add(
208 cb.or(
209 cb.like(root.get("title"), '%' + content + '%'),
210 cb.and(
211 cb.notEqual(root.get("type"), Post.Type.IMG),
212 cb.like(root.get("content"), '%' + content + '%')
213 )));
214 } else {
215 predicates.add(cb.like(root.get("title"), '%' + content + '%'));
216 }
217 }
218
219 if(joinUserFollows != null){
220 Join<Object, Object> joinFollow = root.join("section").join("follows");
221 predicates.add(cb.equal(joinFollow.get("user"), joinUserFollows));
222 }
223
224 cq.where(cb.and(predicates.toArray(Predicate[]::new)));
225
226 switch (sortCriteria) {
227 case MOSTVOTED:
228 cq.orderBy(cb.desc(root.get("votesCount")));
229 break;
230 case OLDEST:
231 cq.orderBy(cb.asc(root.get("creationDate")));
232 break;
233 case NEWEST:
234 default:
235 cq.orderBy(cb.desc(root.get("creationDate")));
236 break;
237 }
238
239
240 TypedQuery<Post> tq = em.createQuery(cq);
241 if(offset >= 0)
242 tq.setFirstResult(offset);
243 if(pageSize>=0)
244 tq.setMaxResults(pageSize);
245
246 return tq.getResultList();
247 }
248 }
249 }