diff --git a/src/main/java/de/bstly/board/businesslogic/EntryManager.java b/src/main/java/de/bstly/board/businesslogic/EntryManager.java index 4568d9d..c8e3239 100644 --- a/src/main/java/de/bstly/board/businesslogic/EntryManager.java +++ b/src/main/java/de/bstly/board/businesslogic/EntryManager.java @@ -17,6 +17,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Order; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import com.google.common.collect.Lists; import com.querydsl.core.types.OrderSpecifier; @@ -43,6 +44,8 @@ public class EntryManager { @Autowired private EntryRepository entryRepository; @Autowired + private TagManager tagManager; + @Autowired private CommentManager commentManager; @Autowired private VoteManager voteManager; @@ -73,40 +76,45 @@ public class EntryManager { + UPVOTES_QUERY + ") AS upvote ON upvote.target = entry.id LEFT JOIN (" + DOWNVOTES_QUERY - + ") AS downvote ON downvote.target = entry.id WHERE %s ORDER BY ranking DESC, entry.created DESC"; + + ") AS downvote ON downvote.target = entry.id %s"; - static final String DATE_QUERY = "SELECT entry.*FROM entries AS entry WHERE %s ORDER BY entry.created DESC"; + static final String DATE_QUERY = "SELECT entry.* FROM entries AS entry %s"; + + static final String USER_QUERY = "SELECT entry.* FROM entries AS entry %s ORDER BY entry.created :order"; static final String COMMENT_CALCULATION_QUERY = "SELECT entry.*, IFNULL(comment.count,0) as comments, IFNULL(comment.count,0) / IF(:gravity > 0, POW(TIMESTAMPDIFF(HOUR, comment.last, :before)+2,:gravity), 1) AS ranking FROM entries AS entry LEFT JOIN (" + COMMENTS_QUERY - + ") AS comment ON comment.target = entry.id WHERE %s ORDER BY ranking DESC, entry.created DESC"; + + ") AS comment ON comment.target = entry.id %s"; static final String LAST_COMMENT_QUERY = "SELECT entry.* FROM entries AS entry LEFT JOIN (" + COMMENTS_QUERY - + ") AS comment ON comment.target = entry.id WHERE %s ORDER BY comment.last DESC, entry.created DESC"; + + ") AS comment ON comment.target = entry.id %s "; - static final String COUNT_QUERY = "SELECT count(entry.id) FROM entries as entry WHERE %s"; + static final String COUNT_QUERY = "SELECT count(entry.id) FROM entries as entry %s"; /** * Fetch by ranking. * - * @param username the username - * @param date the date + * @param username the username + * @param date the date * @param flaggedStatus the flagged status - * @param gravity the gravity - * @param page the page - * @param size the size + * @param tag the tag + * @param gravity the gravity + * @param page the page + * @param size the size + * @param asc the asc * @return the page */ public Page fetchByRanking(String username, Instant date, FlaggedStatus flaggedStatus, - double gravity, int page, int size) { - Query query = createEntryQuery(RANK_CALCULATION_QUERY, username, date, flaggedStatus); + String tag, double gravity, int page, int size, boolean asc) { + Query query = createEntryQuery(RANK_CALCULATION_QUERY, username, date, flaggedStatus, tag, + null, asc ? "ranking ASC, entry.created ASC" : "ranking DESC, entry.created DESC"); query.setParameter("gravity", gravity); query.setFirstResult((page) * size); query.setMaxResults(size); @SuppressWarnings("unchecked") List list = query.getResultList(); - Query queryTotal = createCountQuery(COUNT_QUERY, username, date, flaggedStatus); + Query queryTotal = createCountQuery(COUNT_QUERY, username, date, flaggedStatus, tag, null); long countResult = ((BigInteger) queryTotal.getSingleResult()).longValue(); return new PageImpl(list, PageRequest.of(page, size), countResult); } @@ -114,21 +122,24 @@ public class EntryManager { /** * Fetch by date. * - * @param username the username - * @param date the date + * @param username the username + * @param date the date * @param flaggedStatus the flagged status - * @param page the page - * @param size the size + * @param tag the tag + * @param page the page + * @param size the size + * @param asc the asc * @return the page */ public Page fetchByDate(String username, Instant date, FlaggedStatus flaggedStatus, - int page, int size) { - Query query = createEntryQuery(DATE_QUERY, username, date, flaggedStatus); + String tag, int page, int size, boolean asc) { + Query query = createEntryQuery(DATE_QUERY, username, date, flaggedStatus, tag, null, + asc ? "entry.created ASC" : "entry.created DESC"); query.setFirstResult((page) * size); query.setMaxResults(size); @SuppressWarnings("unchecked") List list = query.getResultList(); - Query queryTotal = createCountQuery(COUNT_QUERY, username, date, flaggedStatus); + Query queryTotal = createCountQuery(COUNT_QUERY, username, date, flaggedStatus, tag, null); long countResult = ((BigInteger) queryTotal.getSingleResult()).longValue(); return new PageImpl(list, PageRequest.of(page, size), countResult); } @@ -136,23 +147,27 @@ public class EntryManager { /** * Fetch by comments. * - * @param username the username - * @param date the date + * @param username the username + * @param date the date * @param flaggedStatus the flagged status - * @param gravity the gravity - * @param page the page - * @param size the size + * @param tag the tag + * @param gravity the gravity + * @param page the page + * @param size the size + * @param asc the asc * @return the page */ public Page fetchByComments(String username, Instant date, FlaggedStatus flaggedStatus, - double gravity, int page, int size) { - Query query = createEntryQuery(COMMENT_CALCULATION_QUERY, username, date, flaggedStatus); + String tag, double gravity, int page, int size, boolean asc) { + Query query = createEntryQuery(COMMENT_CALCULATION_QUERY, username, date, flaggedStatus, + tag, null, + asc ? "ranking ASC, entry.created ASC" : "ranking DESC, entry.created DESC"); query.setParameter("gravity", gravity); query.setFirstResult((page) * size); query.setMaxResults(size); @SuppressWarnings("unchecked") List list = query.getResultList(); - Query queryTotal = createCountQuery(COUNT_QUERY, username, date, flaggedStatus); + Query queryTotal = createCountQuery(COUNT_QUERY, username, date, flaggedStatus, tag, null); long countResult = ((BigInteger) queryTotal.getSingleResult()).longValue(); return new PageImpl(list, PageRequest.of(page, size), countResult); } @@ -160,21 +175,54 @@ public class EntryManager { /** * Fetch by last comment. * - * @param username the username - * @param date the date + * @param username the username + * @param date the date * @param flaggedStatus the flagged status - * @param page the page - * @param size the size + * @param tag the tag + * @param page the page + * @param size the size + * @param asc the asc * @return the page */ public Page fetchByLastComment(String username, Instant date, - FlaggedStatus flaggedStatus, int page, int size) { - Query query = createEntryQuery(LAST_COMMENT_QUERY, username, date, flaggedStatus); + FlaggedStatus flaggedStatus, String tag, int page, int size, boolean asc) { + Query query = createEntryQuery(LAST_COMMENT_QUERY, username, date, flaggedStatus, tag, null, + asc ? "comment.last ASC, entry.created ASC" + : "comment.last DESC, entry.created DESC"); query.setFirstResult((page) * size); query.setMaxResults(size); @SuppressWarnings("unchecked") List list = query.getResultList(); - Query queryTotal = createCountQuery(COUNT_QUERY, username, date, flaggedStatus); + Query queryTotal = createCountQuery(COUNT_QUERY, username, date, flaggedStatus, tag, null); + long countResult = ((BigInteger) queryTotal.getSingleResult()).longValue(); + return new PageImpl(list, PageRequest.of(page, size), countResult); + } + + /** + * Fetch by user. + * + * @param fromUser the from user + * @param username the username + * @param date the date + * @param flaggedStatus the flagged status + * @param tag the tag + * @param page the page + * @param size the size + * @param asc the asc + * @return the page + */ + public Page fetchByUser(String fromUser, String username, Instant date, + FlaggedStatus flaggedStatus, String tag, int page, int size, boolean asc) { + Query query = createEntryQuery(DATE_QUERY, username, date, flaggedStatus, tag, + "AND entry.author = :username", asc ? "entry.created ASC" : "entry.created DESC"); + query.setParameter("username", username); + query.setFirstResult((page) * size); + query.setMaxResults(size); + @SuppressWarnings("unchecked") + List list = query.getResultList(); + Query queryTotal = createCountQuery(COUNT_QUERY, username, date, flaggedStatus, tag, + "AND entry.author = :username"); + queryTotal.setParameter("username", username); long countResult = ((BigInteger) queryTotal.getSingleResult()).longValue(); return new PageImpl(list, PageRequest.of(page, size), countResult); } @@ -182,32 +230,52 @@ public class EntryManager { /** * Creates the entry query. * - * @param rawQuery the raw query - * @param username the username - * @param date the date + * @param rawQuery the raw query + * @param username the username + * @param date the date * @param flaggedStatus the flagged status + * @param tag the tag + * @param additional the additional + * @param orderBy the order by * @return the query */ protected Query createEntryQuery(String rawQuery, String username, Instant date, - FlaggedStatus flaggedStatus) { + FlaggedStatus flaggedStatus, String tag, String additional, String orderBy) { String filterString = ""; + if (StringUtils.hasText(tag)) { + filterString += " INNER JOIN tags as tag ON entry.id = tag.target AND tag.tag = '" + + tag + + "'"; + } + boolean author = false; if (date != null) { - filterString = "entry.created < :before"; + filterString += " WHERE entry.created < :before"; } else { date = Instant.now(); author = true; - filterString = "(entry.created < :before OR entry.author = :author)"; + filterString += " WHERE (entry.created < :before OR entry.author = :author)"; } filterString += " AND entry.flagged_status = :flag"; + if (StringUtils.hasText(additional)) { + filterString += " " + + additional; + } + + if (StringUtils.hasText(orderBy)) { + filterString += " ORDER BY " + + orderBy; + } + Query query = em.createNativeQuery(String.format(rawQuery, filterString), Entry.class); query.setParameter("before", date); if (author) { query.setParameter("author", username); } + query.setParameter("flag", flaggedStatus.toString()); return query; @@ -216,27 +284,40 @@ public class EntryManager { /** * Creates the count query. * - * @param rawQuery the raw query - * @param username the username - * @param date the date + * @param rawQuery the raw query + * @param username the username + * @param date the date * @param flaggedStatus the flagged status + * @param tag the tag + * @param additional the additional * @return the query */ protected Query createCountQuery(String rawQuery, String username, Instant date, - FlaggedStatus flaggedStatus) { + FlaggedStatus flaggedStatus, String tag, String additional) { String filterString = ""; + if (StringUtils.hasText(tag)) { + filterString += " INNER JOIN tags as tag ON entry.id = tag.target AND tag.tag = '" + + tag + + "'"; + } + boolean author = false; if (date != null) { - filterString = "entry.created < :before"; + filterString += "WHERE entry.created < :before"; } else { date = Instant.now(); author = true; - filterString = "(entry.created < :before OR entry.author = :author)"; + filterString += "WHERE (entry.created < :before OR entry.author = :author)"; } filterString += " AND entry.flagged_status = :flag"; + if (StringUtils.hasText(additional)) { + filterString += " " + + additional; + } + Query query = em.createNativeQuery(String.format(rawQuery, filterString)); query.setParameter("before", date); if (author) { @@ -252,7 +333,7 @@ public class EntryManager { * * @param page the page * @param size the size - * @param asc the asc + * @param asc the asc * @return the page */ public Page fetchFlagged(int page, int size, boolean asc) { @@ -267,29 +348,12 @@ public class EntryManager { query.fetchCount()); } - /** - * Fetch by user. - * - * @param username the username - * @param date the date - * @param page the page - * @param size the size - * @param asc the asc - * @return the page - */ - public Page fetchByUser(String username, Instant date, int page, int size, boolean asc) { - Sort sort = Sort.by(asc ? Order.asc("created") : Order.desc("created")); - return entryRepository.findAll( - qEntry.author.equalsIgnoreCase(username).and(qEntry.created.before(date)), - PageRequest.of(page, size, sort)); - } - /** * Fetch by bookmarks. * * @param username the username - * @param page the page - * @param size the size + * @param page the page + * @param size the size * @return the page */ public Page fetchByBookmarks(String username, int page, int size) { @@ -307,14 +371,25 @@ public class EntryManager { * Apply metadata. * * @param username the username - * @param karma the karma - * @param entry the entry - * @param ignore the ignore + * @param karma the karma + * @param entry the entry + * @param ignore the ignore */ public void applyMetadata(String username, long karma, Entry entry, List ignore) { + entry.setTags(tagManager.getForTarget(entry.getId())); + ignore.addAll(entry.getMetadata().keySet()); + if (!ignore.contains("author")) { + entry.getMetadata().put("author", entry.getAuthor().equals(username)); + } + + if (!ignore.contains("edit")) { + entry.getMetadata().put("edit", entry.getAuthor().equals(username) + && entry.getCreated().isAfter(Instant.now())); + } + if (!ignore.contains("comments")) { entry.getMetadata().put("comments", commentManager.count(entry.getId())); } @@ -383,9 +458,9 @@ public class EntryManager { * Apply metadata. * * @param username the username - * @param karma the karma - * @param entries the entries - * @param ignore the ignore + * @param karma the karma + * @param entries the entries + * @param ignore the ignore */ public void applyMetadata(String username, long karma, List entries, List ignore) { @@ -421,7 +496,10 @@ public class EntryManager { * @return the entry */ public Entry save(Entry entry) { - return entryRepository.save(entry); + List tags = Lists.newArrayList(entry.getTags()); + entry = entryRepository.save(entry); + tagManager.setForTarget(entry.getId(), tags); + return entry; } /** @@ -430,6 +508,7 @@ public class EntryManager { * @param entry the entry */ public void delete(Entry entry) { + tagManager.deleteByTarget(entry.getId()); commentManager.deleteByTarget(entry.getId()); voteManager.deleteByTarget(entry.getId(), Types.entry); bookmarksManager.removeEntry(entry.getId()); @@ -454,7 +533,7 @@ public class EntryManager { /** * Gets the user points. * - * @param entryId the entry id + * @param entryId the entry id * @param username the username * @return the user points */ diff --git a/src/main/java/de/bstly/board/businesslogic/TagManager.java b/src/main/java/de/bstly/board/businesslogic/TagManager.java new file mode 100644 index 0000000..99681d7 --- /dev/null +++ b/src/main/java/de/bstly/board/businesslogic/TagManager.java @@ -0,0 +1,96 @@ +/** + * + */ +package de.bstly.board.businesslogic; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.querydsl.jpa.impl.JPAQueryFactory; + +import de.bstly.board.model.QTag; +import de.bstly.board.model.Tag; +import de.bstly.board.repository.TagRepository; + +/** + * The Class TagManager. + */ +@Component +public class TagManager { + + @Autowired + private JPAQueryFactory jpaQueryFactory; + @Autowired + private TagRepository tagRepository; + private QTag qTag = QTag.tag1; + + /** + * Creates the. + * + * @param tag the tag + * @param target the target + * @return the tag + */ + public Tag create(String tag, Long target) { + return tagRepository.save(new Tag(tag, target)); + } + + /** + * Delete. + * + * @param tag the tag + * @param target the target + */ + public void delete(String tag, Long target) { + tagRepository.deleteById(new Tag(tag, target)); + } + + /** + * Gets the for target. + * + * @param target the target + * @return the for target + */ + public List getForTarget(Long target) { + return jpaQueryFactory.selectFrom(qTag).where(qTag.target.eq(target)).select(qTag.tag) + .fetch(); + } + + /** + * Sets the for target. + * + * @param target the target + * @param tags the tags + */ + public void setForTarget(Long target, List tags) { + deleteByTarget(target); + if (tags != null) { + for (String tag : tags) { + create(tag, target); + } + } + } + + /** + * Delete by target. + * + * @param target the target + */ + public void deleteByTarget(Long target) { + tagRepository.deleteAll(tagRepository.findAll(qTag.target.eq(target))); + } + + /** + * Search. + * + * @param search the search + * @return the list + */ + public List search(String search) { + return jpaQueryFactory.selectFrom(qTag).where(qTag.tag.containsIgnoreCase(search)) + .distinct().limit(10).select(qTag.tag).fetch(); + } + +} diff --git a/src/main/java/de/bstly/board/businesslogic/UserManager.java b/src/main/java/de/bstly/board/businesslogic/UserManager.java index 2dc7be0..1743ce2 100644 --- a/src/main/java/de/bstly/board/businesslogic/UserManager.java +++ b/src/main/java/de/bstly/board/businesslogic/UserManager.java @@ -125,6 +125,12 @@ public class UserManager implements UserDetailsService, SmartInitializingSinglet /* * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ + /* + * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) + */ /* * @see org.springframework.security.core.userdetails.UserDetailsService# * loadUserByUsername(java.lang.String) @@ -224,6 +230,12 @@ public class UserManager implements UserDetailsService, SmartInitializingSinglet /* * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ + /* + * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + */ /* * @see org.springframework.beans.factory.SmartInitializingSingleton# * afterSingletonsInstantiated() diff --git a/src/main/java/de/bstly/board/controller/EntryController.java b/src/main/java/de/bstly/board/controller/EntryController.java index 97d9029..52fc30e 100644 --- a/src/main/java/de/bstly/board/controller/EntryController.java +++ b/src/main/java/de/bstly/board/controller/EntryController.java @@ -64,11 +64,13 @@ public class EntryController extends BaseController { /** * Fetch by ranking. * - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter + * @param tagParameter the tag parameter * @param gravityParameter the gravity parameter - * @param ignoreParameter the ignore parameter + * @param ascParameter the asc parameter + * @param ignoreParameter the ignore parameter * @return the page */ @PreAuthorize("isAuthenticated()") @@ -76,7 +78,9 @@ public class EntryController extends BaseController { public Page fetchByRanking(@RequestParam("page") Optional pageParameter, @RequestParam("size") Optional sizeParameter, @RequestParam("date") Optional dateParameter, + @RequestParam("tag") Optional tagParameter, @RequestParam("gravity") Optional gravityParameter, + @RequestParam("asc") Optional ascParameter, @RequestParam("ignore") Optional> ignoreParameter) { if (sizeParameter.isPresent() && sizeParameter.get() > 100) { @@ -92,9 +96,9 @@ public class EntryController extends BaseController { } Page entries = entryManager.fetchByRanking(getCurrentUsername(), - dateParameter.orElse(null), FlaggedStatus.NORMAL, + dateParameter.orElse(null), FlaggedStatus.NORMAL, tagParameter.orElse(null), gravityParameter.orElse(getGravity()), pageParameter.orElse(0), - sizeParameter.orElse(settingsManager.getPageSize())); + sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false)); List ignore = ignoreParameter.orElse(Lists.newArrayList()); entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), @@ -105,9 +109,11 @@ public class EntryController extends BaseController { /** * Fetch by date. * - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter + * @param tagParameter the tag parameter + * @param ascParameter the asc parameter * @param ignoreParameter the ignore parameter * @return the page */ @@ -116,113 +122,7 @@ public class EntryController extends BaseController { public Page fetchByDate(@RequestParam("page") Optional pageParameter, @RequestParam("size") Optional sizeParameter, @RequestParam("date") Optional dateParameter, - @RequestParam("ignore") Optional> ignoreParameter) { - - if (sizeParameter.isPresent() && sizeParameter.get() > 100) { - sizeParameter = Optional.of(100); - } - - if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) { - dateParameter = Optional.of(Instant.now()); - } - - Page entries = entryManager.fetchByDate(getCurrentUsername(), - dateParameter.orElse(null), FlaggedStatus.NORMAL, pageParameter.orElse(0), - sizeParameter.orElse(settingsManager.getPageSize())); - List ignore = ignoreParameter.orElse(Lists.newArrayList()); - entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), - entries.getContent(), ignore); - return entries; - } - - /** - * Fetch by comments. - * - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter - * @param gravityParameter the gravity parameter - * @param ignoreParameter the ignore parameter - * @return the page - */ - @PreAuthorize("isAuthenticated()") - @GetMapping("/comments") - public Page fetchByComments(@RequestParam("page") Optional pageParameter, - @RequestParam("size") Optional sizeParameter, - @RequestParam("date") Optional dateParameter, - @RequestParam("gravity") Optional gravityParameter, - @RequestParam("ignore") Optional> ignoreParameter) { - - if (sizeParameter.isPresent() && sizeParameter.get() > 100) { - sizeParameter = Optional.of(100); - } - - if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) { - dateParameter = Optional.of(Instant.now()); - } - - Page entries = entryManager.fetchByComments(getCurrentUsername(), - dateParameter.orElse(null), FlaggedStatus.NORMAL, - gravityParameter.orElse(getGravity()), pageParameter.orElse(0), - sizeParameter.orElse(settingsManager.getPageSize())); - - List ignore = ignoreParameter.orElse(Lists.newArrayList()); - entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), - entries.getContent(), ignore); - return entries; - } - - /** - * Fetch by last. - * - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter - * @param ignoreParameter the ignore parameter - * @return the page - */ - @PreAuthorize("isAuthenticated()") - @GetMapping("/last") - public Page fetchByLast(@RequestParam("page") Optional pageParameter, - @RequestParam("size") Optional sizeParameter, - @RequestParam("date") Optional dateParameter, - @RequestParam("ignore") Optional> ignoreParameter) { - - if (sizeParameter.isPresent() && sizeParameter.get() > 100) { - sizeParameter = Optional.of(100); - } - - if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) { - dateParameter = Optional.of(Instant.now()); - } - - Page entries = entryManager.fetchByLastComment(getCurrentUsername(), - dateParameter.orElse(null), FlaggedStatus.NORMAL, pageParameter.orElse(0), - sizeParameter.orElse(settingsManager.getPageSize())); - - List ignore = ignoreParameter.orElse(Lists.newArrayList()); - entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), - entries.getContent(), ignore); - return entries; - } - - /** - * Fetch by user. - * - * @param username the username - * @param pageParameter the page parameter - * @param sizeParameter the size parameter - * @param dateParameter the date parameter - * @param ascParameter the asc parameter - * @param ignoreParameter the ignore parameter - * @return the page - */ - @PreAuthorize("isAuthenticated()") - @GetMapping("/byuser/{username}") - public Page fetchByUser(@PathVariable("username") String username, - @RequestParam("page") Optional pageParameter, - @RequestParam("size") Optional sizeParameter, - @RequestParam("date") Optional dateParameter, + @RequestParam("tag") Optional tagParameter, @RequestParam("asc") Optional ascParameter, @RequestParam("ignore") Optional> ignoreParameter) { @@ -234,9 +134,130 @@ public class EntryController extends BaseController { dateParameter = Optional.of(Instant.now()); } - Page entries = entryManager.fetchByUser(username, - dateParameter.orElse(Instant.now()), pageParameter.orElse(0), + Page entries = entryManager.fetchByDate(getCurrentUsername(), + dateParameter.orElse(null), FlaggedStatus.NORMAL, tagParameter.orElse(null), + pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()), + ascParameter.orElse(false)); + List ignore = ignoreParameter.orElse(Lists.newArrayList()); + entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), + entries.getContent(), ignore); + return entries; + } + + /** + * Fetch by comments. + * + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter + * @param tagParameter the tag parameter + * @param gravityParameter the gravity parameter + * @param ascParameter the asc parameter + * @param ignoreParameter the ignore parameter + * @return the page + */ + @PreAuthorize("isAuthenticated()") + @GetMapping("/comments") + public Page fetchByComments(@RequestParam("page") Optional pageParameter, + @RequestParam("size") Optional sizeParameter, + @RequestParam("date") Optional dateParameter, + @RequestParam("tag") Optional tagParameter, + @RequestParam("gravity") Optional gravityParameter, + @RequestParam("asc") Optional ascParameter, + @RequestParam("ignore") Optional> ignoreParameter) { + + if (sizeParameter.isPresent() && sizeParameter.get() > 100) { + sizeParameter = Optional.of(100); + } + + if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) { + dateParameter = Optional.of(Instant.now()); + } + + Page entries = entryManager.fetchByComments(getCurrentUsername(), + dateParameter.orElse(null), FlaggedStatus.NORMAL, tagParameter.orElse(null), + gravityParameter.orElse(getGravity()), pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false)); + + List ignore = ignoreParameter.orElse(Lists.newArrayList()); + entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), + entries.getContent(), ignore); + return entries; + } + + /** + * Fetch by last. + * + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter + * @param tagParameter the tag parameter + * @param ascParameter the asc parameter + * @param ignoreParameter the ignore parameter + * @return the page + */ + @PreAuthorize("isAuthenticated()") + @GetMapping("/last") + public Page fetchByLast(@RequestParam("page") Optional pageParameter, + @RequestParam("size") Optional sizeParameter, + @RequestParam("date") Optional dateParameter, + @RequestParam("tag") Optional tagParameter, + @RequestParam("asc") Optional ascParameter, + @RequestParam("ignore") Optional> ignoreParameter) { + + if (sizeParameter.isPresent() && sizeParameter.get() > 100) { + sizeParameter = Optional.of(100); + } + + if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) { + dateParameter = Optional.of(Instant.now()); + } + + Page entries = entryManager.fetchByLastComment(getCurrentUsername(), + dateParameter.orElse(null), FlaggedStatus.NORMAL, tagParameter.orElse(null), + pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()), + ascParameter.orElse(false)); + + List ignore = ignoreParameter.orElse(Lists.newArrayList()); + entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), + entries.getContent(), ignore); + return entries; + } + + /** + * Fetch by user. + * + * @param username the username + * @param pageParameter the page parameter + * @param sizeParameter the size parameter + * @param dateParameter the date parameter + * @param tagParameter the tag parameter + * @param ascParameter the asc parameter + * @param ignoreParameter the ignore parameter + * @return the page + */ + @PreAuthorize("isAuthenticated()") + @GetMapping("/byuser/{username}") + public Page fetchByUser(@PathVariable("username") String username, + @RequestParam("page") Optional pageParameter, + @RequestParam("size") Optional sizeParameter, + @RequestParam("date") Optional dateParameter, + @RequestParam("tag") Optional tagParameter, + @RequestParam("asc") Optional ascParameter, + @RequestParam("ignore") Optional> ignoreParameter) { + + if (sizeParameter.isPresent() && sizeParameter.get() > 100) { + sizeParameter = Optional.of(100); + } + + if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) { + dateParameter = Optional.of(Instant.now()); + } + + Page entries = entryManager.fetchByUser(getCurrentUsername(), username, + dateParameter.orElse(null), FlaggedStatus.NORMAL, tagParameter.orElse(null), + pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()), + ascParameter.orElse(false)); List ignore = ignoreParameter.orElse(Lists.newArrayList()); entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), entries.getContent(), ignore); @@ -246,7 +267,7 @@ public class EntryController extends BaseController { /** * Gets the entry. * - * @param id the id + * @param id the id * @param ignoreParameter the ignore parameter * @return the entry */ @@ -270,7 +291,7 @@ public class EntryController extends BaseController { /** * Creates the entry. * - * @param entry the entry + * @param entry the entry * @param ignoreParameter the ignore parameter * @return the entry */ @@ -311,7 +332,7 @@ public class EntryController extends BaseController { /** * Update entry. * - * @param entry the entry + * @param entry the entry * @param ignoreParameter the ignore parameter * @return the entry */ @@ -319,8 +340,8 @@ public class EntryController extends BaseController { @PatchMapping public Entry updateEntry(@RequestBody Entry entry, @RequestParam("ignore") Optional> ignoreParameter) { - Entry orgEnry = entryManager.get(entry.getId()); - if (orgEnry == null || !orgEnry.getAuthor().equals(getCurrentUsername()) || orgEnry + Entry orgEntry = entryManager.get(entry.getId()); + if (orgEntry == null || !orgEntry.getAuthor().equals(getCurrentUsername()) || orgEntry .getCreated().plus(getEntryDelay(), ChronoUnit.MINUTES).isBefore(Instant.now())) { throw new EntityResponseStatusException(HttpStatus.FORBIDDEN); } @@ -333,15 +354,16 @@ public class EntryController extends BaseController { HttpStatus.UNPROCESSABLE_ENTITY); } - orgEnry.setUrl(entry.getUrl()); - orgEnry.setTitle(entry.getTitle().trim()); - orgEnry.setText(entry.getText().trim()); - orgEnry = entryManager.save(orgEnry); + orgEntry.setUrl(entry.getUrl()); + orgEntry.setTitle(entry.getTitle().trim()); + orgEntry.setText(entry.getText().trim()); + orgEntry.setTags(entry.getTags()); + orgEntry = entryManager.save(orgEntry); List ignore = ignoreParameter.orElse(Lists.newArrayList()); entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), - entry, ignore); - return entry; + orgEntry, ignore); + return orgEntry; } /** diff --git a/src/main/java/de/bstly/board/controller/TagController.java b/src/main/java/de/bstly/board/controller/TagController.java new file mode 100644 index 0000000..71649ee --- /dev/null +++ b/src/main/java/de/bstly/board/controller/TagController.java @@ -0,0 +1,93 @@ +/** + * + */ +package de.bstly.board.controller; + +import java.util.List; +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.google.common.collect.Lists; + +import de.bstly.board.businesslogic.EntryManager; +import de.bstly.board.businesslogic.TagManager; +import de.bstly.board.businesslogic.UserManager; +import de.bstly.board.controller.support.EntityResponseStatusException; +import de.bstly.board.controller.support.RequestBodyErrors; +import de.bstly.board.controller.validation.EntryValidator; +import de.bstly.board.model.Entry; + +/** + * The Class TagController. + */ +@RestController +@RequestMapping("/tags") +public class TagController extends BaseController { + + @Autowired + private TagManager tagManager; + @Autowired + private EntryManager entryManager; + @Autowired + private UserManager userManager; + @Autowired + private EntryValidator entryValidator; + + /** + * Search. + * + * @param query the query + * @return the list + */ + @PreAuthorize("isAuthenticated()") + @GetMapping + public List search(@RequestParam("q") String query) { + return tagManager.search(query); + } + + /** + * Sets the tags. + * + * @param id the id + * @param tags the tags + * @param ignoreParameter the ignore parameter + * @return the entry + */ + @PreAuthorize("isAuthenticated()") + @PatchMapping("/entry/{id}") + public Entry setTags(@PathVariable("id") Long id, @RequestBody List tags, + @RequestParam("ignore") Optional> ignoreParameter) { + Entry entry = entryManager.get(id); + if (entry == null || !entry.getAuthor().equals(getCurrentUsername())) { + throw new EntityResponseStatusException(HttpStatus.FORBIDDEN); + } + + entry.setTags(tags); + + RequestBodyErrors bindingResult = new RequestBodyErrors(entry); + entryValidator.validate(entry, bindingResult); + + if (bindingResult.hasErrors()) { + throw new EntityResponseStatusException(bindingResult.getAllErrors(), + HttpStatus.UNPROCESSABLE_ENTITY); + } + + entry = entryManager.save(entry); + + List ignore = ignoreParameter.orElse(Lists.newArrayList()); + entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()), + entry, ignore); + return entry; + } + +} diff --git a/src/main/java/de/bstly/board/controller/validation/EntryValidator.java b/src/main/java/de/bstly/board/controller/validation/EntryValidator.java index f860200..0cb9b30 100644 --- a/src/main/java/de/bstly/board/controller/validation/EntryValidator.java +++ b/src/main/java/de/bstly/board/controller/validation/EntryValidator.java @@ -52,6 +52,14 @@ public class EntryValidator implements Validator { if (StringUtils.hasText(entry.getUrl()) && !urlValidator.isValid(entry.getUrl())) { errors.rejectValue("url", "INVALID"); } + + if (entry.getTags() != null) { + for (String tag : entry.getTags()) { + if (tag.contains("#")) { + errors.rejectValue("tags", "INVALID", tag); + } + } + } } } diff --git a/src/main/java/de/bstly/board/model/Entry.java b/src/main/java/de/bstly/board/model/Entry.java index 9a7b39f..a486831 100644 --- a/src/main/java/de/bstly/board/model/Entry.java +++ b/src/main/java/de/bstly/board/model/Entry.java @@ -4,6 +4,7 @@ package de.bstly.board.model; import java.time.Instant; +import java.util.List; import java.util.Map; import javax.persistence.Column; @@ -55,6 +56,8 @@ public class Entry { @Column(name = "text") private String text; @Transient + private List tags; + @Transient private Double ranking; @Transient private Long points; @@ -223,6 +226,24 @@ public class Entry { this.text = text; } + /** + * Gets the tags. + * + * @return the tags + */ + public List getTags() { + return tags; + } + + /** + * Sets the tags. + * + * @param tags the new tags + */ + public void setTags(List tags) { + this.tags = tags; + } + /** * Gets the ranking. * diff --git a/src/main/java/de/bstly/board/model/Tag.java b/src/main/java/de/bstly/board/model/Tag.java new file mode 100644 index 0000000..ee111cb --- /dev/null +++ b/src/main/java/de/bstly/board/model/Tag.java @@ -0,0 +1,89 @@ +/** + * + */ +package de.bstly.board.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.Table; + +/** + * The Class Tag. + */ +@Entity +@Table(name = "tags") +@IdClass(Tag.class) +public class Tag implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + @Id + @Column(name = "tag", nullable = false) + private String tag; + @Id + @Column(name = "target", nullable = false) + private Long target; + + /** + * Instantiates a new tag. + */ + public Tag() { + super(); + } + + /** + * Instantiates a new tag. + * + * @param tag the tag + * @param target the target + */ + public Tag(String tag, Long target) { + super(); + this.tag = tag; + this.target = target; + } + + /** + * Gets the tag. + * + * @return the tag + */ + public String getTag() { + return tag; + } + + /** + * Sets the tag. + * + * @param tag the new tag + */ + public void setTag(String tag) { + this.tag = tag; + } + + /** + * Gets the target. + * + * @return the target + */ + public Long getTarget() { + return target; + } + + /** + * Sets the target. + * + * @param target the new target + */ + public void setTarget(Long target) { + this.target = target; + } + +} diff --git a/src/main/java/de/bstly/board/repository/TagRepository.java b/src/main/java/de/bstly/board/repository/TagRepository.java new file mode 100644 index 0000000..ae35460 --- /dev/null +++ b/src/main/java/de/bstly/board/repository/TagRepository.java @@ -0,0 +1,18 @@ +/** + * + */ +package de.bstly.board.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.stereotype.Repository; + +import de.bstly.board.model.Tag; + +/** + * The Interface TagRepository. + */ +@Repository +public interface TagRepository extends JpaRepository, QuerydslPredicateExecutor { + +}