View Javadoc
1   package usecase.post;
2   
3   import media.MediaRepository;
4   import media.ReadLimitExceededException;
5   import media.validation.Image;
6   import model.entity.Post;
7   import model.entity.Section;
8   import model.entity.User;
9   import model.repository.GenericRepository;
10  import model.repository.PostRepository;
11  import model.validation.PostExists;
12  import model.validation.SectionExists;
13  import usecase.auth.AuthenticationRequired;
14  import usecase.auth.AuthorizationException;
15  import usecase.auth.CurrentUser;
16  import usecase.auth.DenyBannedUsers;
17  
18  import javax.enterprise.context.ApplicationScoped;
19  import javax.inject.Inject;
20  import javax.transaction.Transactional;
21  import javax.validation.constraints.NotBlank;
22  import javax.validation.constraints.NotNull;
23  import javax.validation.constraints.Size;
24  import java.io.BufferedInputStream;
25  import java.io.IOException;
26  import java.time.Instant;
27  import java.util.List;
28  import java.util.stream.Collectors;
29  
30  import static model.entity.Post.Type.IMG;
31  import static model.entity.Post.Type.TEXT;
32  import static usecase.post.PostSearchForm.SortCriteria.NEWEST;
33  
34  /**
35   * Classe che fornisce i servizi relativi ai post.
36   */
37  @ApplicationScoped
38  @Transactional
39  public class PostService {
40      private GenericRepository genericRepository;
41      private PostRepository postRepo;
42      private MediaRepository bcRepo;
43      private CurrentUser currentUser;
44  
45      protected PostService(){}
46  
47      @Inject
48      protected PostService(GenericRepository genericRepository, PostRepository postRepo,
49                            MediaRepository bcRepo, CurrentUser currentUser){
50          this.genericRepository = genericRepository;
51          this.postRepo = postRepo;
52          this.bcRepo = bcRepo;
53          this.currentUser = currentUser;
54      }
55  
56      /**
57       * Converte post in PostPage.
58       * @param post post da convertire
59       * @return PostPage con i dati di post
60       */
61      private PostPage mapPost(Post post){
62          User user = null;
63          if(currentUser.isLoggedIn())
64              user = genericRepository.findById(User.class,currentUser.getId());
65  
66          //converte persistence.Post.Type in usecase.post.PostType (ew)
67          PostType postType = post.getType() == IMG ? PostType.IMG : PostType.TEXT;
68  
69          return PostPage.builder()
70                  .id(post.getId())
71                  .title(post.getTitle())
72                  .vote(post.getVote(user) == null ? 0 : post.getVote(user).getVote())
73                  .votes(post.getVotesCount() == null ? 0 : post.getVotesCount())
74                  .sectionName(post.getSection().getName())
75                  .authorName(post.getAuthor().getUsername())
76                  .sectionId(post.getSection().getId())
77                  .authorId(post.getAuthor().getId())
78                  .content(post.getContent())
79                  .creationDate(post.getCreationDate() == null ? Instant.now() : post.getCreationDate())
80                  .nComments(post.getCommentCount())
81                  .type(postType)
82                  .build();
83      }
84  
85      /**
86       * Ritorna un entità DTO relativa ad un post
87       * @param id identificativo post
88       * @return DTO di un post
89       */
90      public PostPage getPost(@PostExists int id){
91          Post p = genericRepository.findById(Post.class,id);
92          return mapPost(p);
93      }
94  
95      /**
96       * Ritorna una lista di post che rispettano determinati parametri
97       * @param form entità con i parametri di ricerca
98       * @return lista di PostPage
99       */
100     @Transactional
101     public List<PostPage> loadPosts(PostSearchForm form){
102         final int elementsPerPage = 10;
103         PostRepository.PostFinder finder = postRepo.getFinder();
104 
105         finder.limit(elementsPerPage);
106 
107         int page = form.getPage() > 0 ? form.getPage() : 1;
108         finder.offset((page == 1) ? 0 : (page-1) * elementsPerPage+1);
109 
110         if(form.getContent() != null) {
111             finder.byContent(form.getContent());
112         }
113         if(form.isIncludeBody()){
114             finder.includeBody();
115         }
116         if(form.getSectionName() != null){
117             Section section = genericRepository.findByNaturalId(Section.class, form.getSectionName());
118             if(section != null){
119                 finder.bySection(section);
120             }
121         }
122         if(form.getAuthorName() != null){
123             User user = genericRepository.findByNaturalId(User.class, form.getAuthorName());
124             if(user != null){
125                 finder.byAuthor(user);
126             }
127         }
128         if(form.isOnlyFollow() && currentUser.isLoggedIn()){
129             finder.joinUserFollows(genericRepository.findById(User.class,currentUser.getId()));
130         }
131         if(form.getPostedAfter() != null){
132             finder.postedAfter(form.getPostedAfter());
133         }
134         if(form.getPostedBefore() != null){
135             finder.postedBefore(form.getPostedBefore());
136         }
137 
138         //null-safe switch
139         switch(form.getOrderBy() != null ? form.getOrderBy() : NEWEST){
140             case NEWEST: default: {
141                 finder.getNewest();
142                 break;
143             }
144             case OLDEST:{
145                 finder.getOldest();
146                 break;
147             }
148             case MOSTVOTED:{
149                 finder.getMostVoted();
150                 break;
151             }
152         }
153         return finder.getResults().stream().map(this::mapPost).collect(Collectors.toList());
154     }
155 
156     /**
157      * Elimina un post dato il suo id
158      * @param id identificativo del post
159      */
160     @AuthenticationRequired //TODO: check autore post?
161     @DenyBannedUsers
162     public void delete(@PostExists int id){
163         Post post = genericRepository.findById(Post.class,id);
164         if(currentUser.getId() != post.getAuthor().getId() && !currentUser.isAdmin())
165             throw new AuthorizationException();
166         genericRepository.remove(genericRepository.findById(User.class,id));
167     }
168 
169     /**
170      * Aggiunge un post ad una sezione
171      * @param title titolo del post
172      * @param body testo del post
173      * @param sectionName nome della sezione
174      * @return identificativo del nuovo post creato
175      */
176     @AuthenticationRequired
177     @DenyBannedUsers
178     public int newPost(@NotBlank String title,
179                        @Size(max=65535) String body,
180                        @NotNull @SectionExists String sectionName){
181         User user = genericRepository.findByNaturalId(User.class, currentUser.getUsername());
182         Section section = genericRepository.findByNaturalId(Section.class,sectionName);
183 
184 
185         Post post = new Post();
186         post.setTitle(title);
187         post.setContent(body == null || body.isBlank() ? "" : body);
188         post.setAuthor(user);
189         post.setSection(section);
190         post.setType(TEXT);
191 
192         return genericRepository.insert(post).getId();
193     }
194 
195     /**
196      * Aggiunge un post ad una sezione
197      * @param title titolo del post
198      * @param content file di tipo immagine
199      * @param sectionName nome della sezione
200      * @return identificativo del nuovo post creato
201      */
202     @AuthenticationRequired
203     @DenyBannedUsers
204     public int newPost(@NotBlank @Size(max=255) String title,
205                        @NotNull @Image BufferedInputStream content,
206                        @NotNull @SectionExists String sectionName){
207         User user = genericRepository.findByNaturalId(User.class,currentUser.getUsername());
208         Section section = genericRepository.findByNaturalId(Section.class,sectionName);
209 
210         String fileName;
211         try {
212             fileName = bcRepo.insert(content);
213         } catch (ReadLimitExceededException e){
214             throw new IllegalArgumentException("Il file non deve superare i 5MB");
215         } catch (IOException e) {
216             throw new RuntimeException(e);
217         }
218 
219         Post post = new Post();
220         post.setTitle(title);
221         post.setAuthor(user);
222         post.setContent(fileName);
223         post.setSection(section);
224         post.setType(IMG);
225 
226         return genericRepository.insert(post).getId(); //in caso di errore il file resta
227     }
228 }