search, refactor userpages

This commit is contained in:
_Bastler 2021-12-03 23:47:17 +01:00
parent 0814f7973c
commit 7dab139268
81 changed files with 674 additions and 443 deletions

BIN
Comment/_4u.cfe Normal file

Binary file not shown.

BIN
Comment/_4u.cfs Normal file

Binary file not shown.

BIN
Comment/_4u.si Normal file

Binary file not shown.

BIN
Comment/_4v.cfe Normal file

Binary file not shown.

BIN
Comment/_4v.cfs Normal file

Binary file not shown.

BIN
Comment/_4v.si Normal file

Binary file not shown.

BIN
Comment/_4y.cfe Normal file

Binary file not shown.

BIN
Comment/_4y.cfs Normal file

Binary file not shown.

BIN
Comment/_4y.si Normal file

Binary file not shown.

BIN
Comment/_4z.fdm Normal file

Binary file not shown.

BIN
Comment/_4z.fdt Normal file

Binary file not shown.

BIN
Comment/_4z.fdx Normal file

Binary file not shown.

BIN
Comment/_4z.fnm Normal file

Binary file not shown.

BIN
Comment/_4z.nvd Normal file

Binary file not shown.

BIN
Comment/_4z.nvm Normal file

Binary file not shown.

BIN
Comment/_4z.si Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene80_0.dvd Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene80_0.dvm Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.doc Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.pos Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.tim Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.tip Normal file

Binary file not shown.

BIN
Comment/_4z_Lucene84_0.tmd Normal file

Binary file not shown.

BIN
Comment/segments_1d Normal file

Binary file not shown.

0
Comment/write.lock Normal file
View File

BIN
Entry/_4d.cfe Normal file

Binary file not shown.

BIN
Entry/_4d.cfs Normal file

Binary file not shown.

BIN
Entry/_4d.si Normal file

Binary file not shown.

BIN
Entry/_4h.cfe Normal file

Binary file not shown.

BIN
Entry/_4h.cfs Normal file

Binary file not shown.

BIN
Entry/_4h.si Normal file

Binary file not shown.

BIN
Entry/_4k.fdm Normal file

Binary file not shown.

BIN
Entry/_4k.fdt Normal file

Binary file not shown.

BIN
Entry/_4k.fdx Normal file

Binary file not shown.

BIN
Entry/_4k.fnm Normal file

Binary file not shown.

BIN
Entry/_4k.nvd Normal file

Binary file not shown.

BIN
Entry/_4k.nvm Normal file

Binary file not shown.

BIN
Entry/_4k.si Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene80_0.dvd Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene80_0.dvm Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.doc Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.pos Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.tim Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.tip Normal file

Binary file not shown.

BIN
Entry/_4k_Lucene84_0.tmd Normal file

Binary file not shown.

BIN
Entry/segments_19 Normal file

Binary file not shown.

0
Entry/write.lock Normal file
View File

15
pom.xml
View File

@ -10,7 +10,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>11</java.version>
<revision>1.2.0</revision>
<revision>1.3.0</revision>
</properties>
<parent>
@ -57,6 +57,19 @@
<artifactId>spring-session-jdbc</artifactId>
</dependency>
<!-- Search -->
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm</artifactId>
<version>6.0.7.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-backend-lucene</artifactId>
<version>6.0.7.Final</version>
</dependency>
<!-- Query DSL -->
<dependency>
<groupId>com.querydsl</groupId>

View File

@ -19,13 +19,13 @@ import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import de.bstly.board.model.Comment;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.QComment;
import de.bstly.board.model.QEntry;
import de.bstly.board.model.QFlag;
import de.bstly.board.model.QVote;
import de.bstly.board.model.Types;
import de.bstly.board.model.VoteType;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
import de.bstly.board.repository.CommentRepository;
import de.bstly.board.repository.VoteRepository;

View File

@ -27,12 +27,12 @@ import com.querydsl.jpa.impl.JPAQueryFactory;
import de.bstly.board.controller.model.EntryFilter;
import de.bstly.board.model.Bookmarks;
import de.bstly.board.model.Entry;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.QEntry;
import de.bstly.board.model.QFlag;
import de.bstly.board.model.QVote;
import de.bstly.board.model.Types;
import de.bstly.board.model.VoteType;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
import de.bstly.board.repository.EntryRepository;
import de.bstly.board.repository.VoteRepository;
@ -104,7 +104,7 @@ public class EntryManager {
* @param asc the asc
* @return the page
*/
public Page<Entry> fetchByRanking(String username, EntryFilter filter, double gravity, int page,
public Page<Entry> fetchByRanking(String username, EntryFilter filter, float gravity, int page,
int size, boolean asc) {
Query query = createEntryQuery(RANK_CALCULATION_QUERY, username, filter,
asc ? "ranking ASC, entry.created ASC" : "ranking DESC, entry.created DESC");
@ -152,7 +152,7 @@ public class EntryManager {
* @param asc the asc
* @return the page
*/
public Page<Entry> fetchByComments(String username, EntryFilter filter, double gravity,
public Page<Entry> fetchByComments(String username, EntryFilter filter, float gravity,
int page, int size, boolean asc) {
Query query = createEntryQuery(COMMENT_CALCULATION_QUERY, username, filter,
asc ? "ranking ASC, entry.created ASC" : "ranking DESC, entry.created DESC");
@ -248,6 +248,24 @@ public class EntryManager {
+ ")";
}
String fixedTagsString = "";
if (filter.getFixedTags() != null && !filter.getFixedTags().isEmpty()) {
for (int index = 0; index < filter.getFixedTags().size(); index++) {
fixedTagsString += "'"
+ filter.getFixedTags().get(index)
+ "'";
if (index < filter.getFixedTags().size() - 1) {
fixedTagsString += ",";
}
}
}
if (StringUtils.hasText(fixedTagsString)) {
filterString += " INNER JOIN tags as fixedTag ON entry.id = fixedTag.target AND fixedTag.tag IN ("
+ fixedTagsString
+ ")";
}
boolean author = false;
if (filter.getDate() != null) {
filterString += " WHERE entry.created < :before";
@ -290,6 +308,24 @@ public class EntryManager {
+ "))";
}
String fixedExcludedTagsString = "";
if (filter.getFixedExcludedTags() != null && !filter.getFixedExcludedTags().isEmpty()) {
for (int index = 0; index < filter.getFixedExcludedTags().size(); index++) {
fixedExcludedTagsString += "'"
+ filter.getFixedExcludedTags().get(index)
+ "'";
if (index < filter.getFixedExcludedTags().size() - 1) {
fixedExcludedTagsString += ",";
}
}
}
if (StringUtils.hasText(fixedExcludedTagsString)) {
filterString += " AND NOT EXISTS (SELECT * FROM tags as fixedExcludedTag WHERE entry.id = fixedExcludedTag.target AND fixedExcludedTag.tag IN ("
+ fixedExcludedTagsString
+ "))";
}
if (StringUtils.hasText(orderBy)) {
filterString += " ORDER BY "
+ orderBy;

View File

@ -10,10 +10,10 @@ import org.springframework.util.Assert;
import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry;
import de.bstly.board.model.Flag;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.QComment;
import de.bstly.board.model.QFlag;
import de.bstly.board.model.Types;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.Types;
import de.bstly.board.repository.CommentRepository;
import de.bstly.board.repository.FlagRepository;

View File

@ -0,0 +1,113 @@
/**
*
*/
package de.bstly.board.businesslogic;
import java.util.List;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import org.hibernate.search.engine.search.query.SearchResult;
import org.hibernate.search.mapper.orm.Search;
import org.hibernate.search.mapper.orm.massindexing.MassIndexer;
import org.hibernate.search.mapper.orm.session.SearchSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import com.google.common.collect.Lists;
import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry;
import de.bstly.board.model.support.Types;
/**
* The Class SearchManager.
*/
@Component
public class SearchManager implements SmartInitializingSingleton {
private Logger logger = LoggerFactory.getLogger(SearchManager.class);
@Autowired
private EntityManager em;
@Autowired
private SettingsManager settingsManager;
private SearchSession searchSession;
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
@Override
public void afterSingletonsInstantiated() {
searchSession = Search.session(em);
}
/**
* On application event.
*
* @param event the event
*/
@EventListener(ContextRefreshedEvent.class)
@Transactional
public void onApplicationEvent(ContextRefreshedEvent event) {
MassIndexer indexer = searchSession.massIndexer().idFetchSize(150)
.batchSizeToLoadObjects(25).threadsToLoadObjects(12);
try {
logger.info("start indexing!");
indexer.startAndWait();
logger.info("finished indexing!");
} catch (InterruptedException e) {
logger.error("error on indexing!", e);
Thread.currentThread().interrupt();
}
}
@Transactional
public SearchResult<Object> search(List<Types> types, String search, int page, int size,
boolean asc, boolean sortByDate) {
List<Class<? extends Object>> classes = Lists.newArrayList();
for (Types type : types) {
switch (type) {
case comment:
classes.add(Comment.class);
break;
case entry:
classes.add(Entry.class);
break;
default:
break;
}
}
if (classes.contains(Entry.class)) {
return searchSession.search(classes)
.where(f -> f.bool()
.should(f.match().field("title").matching(search)
.boost(settingsManager.getGravity()))
.should(f.match().field("text").matching(search)))
.sort(f -> sortByDate
? (asc ? f.field("created").asc() : f.field("created").desc())
: (asc ? f.score().asc() : f.score().desc()))
.fetch(page * size, size);
} else {
return searchSession.search(classes)
.where(f -> f.bool().should(f.match().field("text").matching(search)))
.sort(f -> sortByDate
? (asc ? f.field("created").asc() : f.field("created").desc())
: (asc ? f.score().asc() : f.score().desc()))
.fetch(page * size, size);
}
}
}

View File

@ -13,7 +13,7 @@ import org.springframework.stereotype.Component;
public class SettingsManager {
@Value("${bstly.board.ranking.gravity:1.2}")
private double GRAVITY;
private float GRAVITY;
@Value("${bstly.board.size:30}")
private int SIZE;
@Value("${bstly.board.entry.changePeriod:1}")
@ -26,7 +26,7 @@ public class SettingsManager {
private long FLAG_THRESH;
@Value("${bstly.board.maxTags:3}")
private int MAX_TAGS;
@Value("${bstly.board.maxUserPage:5}")
@Value("${bstly.board.maxUserPage:10}")
private long MAX_USER_PAGES;
/**
@ -34,7 +34,7 @@ public class SettingsManager {
*
* @return the gravity
*/
public double getGravity() {
public float getGravity() {
return GRAVITY;
}

View File

@ -140,6 +140,9 @@ 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)
@ -254,6 +257,9 @@ 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()

View File

@ -8,11 +8,13 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import de.bstly.board.model.QUserPage;
import de.bstly.board.model.UserPage;
import de.bstly.board.model.support.UserPageSorting;
import de.bstly.board.repository.UserPageRepository;
/**
@ -80,10 +82,10 @@ public class UserPageManager {
* @param desc the desc
* @return the by user
*/
public Page<UserPage> getByUser(String username, int page, int size, String sortBy,
boolean desc) {
public Page<UserPage> getByUser(String username, int page, int size, boolean desc) {
return userPageRepository.findAll(qUserPage.username.equalsIgnoreCase(username),
PageRequest.of(page, size, Sort.by(desc ? Direction.DESC : Direction.ASC, sortBy)));
PageRequest.of(page, size, desc ? Sort.by(Order.desc("index"), Order.desc("name"))
: Sort.by(Order.asc("index"), Order.asc("name"))));
}
/**
@ -123,4 +125,40 @@ public class UserPageManager {
Assert.isTrue(exists(username, name), "UserPage not found!");
userPageRepository.delete(get(username, name));
}
public void createDefault(String username) {
if (!exists(username, "TOP")) {
UserPage userPageTop = new UserPage();
userPageTop.setName("TOP");
userPageTop.setUsername(username);
userPageTop.setSorting(UserPageSorting.TOP);
userPageTop.setIndex(20);
save(userPageTop);
}
if (!exists(username, "NEW")) {
UserPage userPageNew = new UserPage();
userPageNew.setName("NEW");
userPageNew.setUsername(username);
userPageNew.setSorting(UserPageSorting.NEW);
userPageNew.setIndex(40);
save(userPageNew);
}
if (!exists(username, "HOT")) {
UserPage userPageHot = new UserPage();
userPageHot.setName("HOT");
userPageHot.setUsername(username);
userPageHot.setSorting(UserPageSorting.HOT);
userPageHot.setIndex(60);
userPageHot.setDivider(true);
save(userPageHot);
}
if (!exists(username, "LAST")) {
UserPage userPageLast = new UserPage();
userPageLast.setName("LAST");
userPageLast.setUsername(username);
userPageLast.setSorting(UserPageSorting.LAST);
userPageLast.setIndex(80);
save(userPageLast);
}
}
}

View File

@ -7,9 +7,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import de.bstly.board.model.QVote;
import de.bstly.board.model.Types;
import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
import de.bstly.board.repository.VoteRepository;
/**

View File

@ -80,13 +80,13 @@ public class BaseController {
*
* @return the gravity
*/
protected double getGravity() {
protected float getGravity() {
String username = getCurrentUsername();
if (username != null) {
LocalUser localUser = userManager.getByUsername(username);
if (localUser.getSettings() != null && localUser.getSettings().containsKey("gravity")) {
try {
double gravity = Double.parseDouble(localUser.getSettings().get("gravity"));
float gravity = Float.parseFloat(localUser.getSettings().get("gravity"));
if (gravity < 0) {
return 0;
}

View File

@ -31,10 +31,10 @@ import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.controller.support.RequestBodyErrors;
import de.bstly.board.controller.validation.CommentValidator;
import de.bstly.board.model.Comment;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.Types;
import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
/**
* The Class CommentController.

View File

@ -21,18 +21,17 @@ import org.springframework.web.bind.annotation.RestController;
import de.bstly.board.businesslogic.EntryManager;
import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry;
import de.bstly.board.model.EntryStatus;
import de.bstly.board.model.EntryType;
import de.bstly.board.model.LocalUser;
import de.bstly.board.model.QLocalUser;
import de.bstly.board.model.Types;
import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType;
import de.bstly.board.model.support.EntryStatus;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
import de.bstly.board.repository.CommentRepository;
import de.bstly.board.repository.LocalUserRepository;
import de.bstly.board.repository.VoteRepository;
/**
* The Class DebugController.
*/
@ -40,78 +39,59 @@ import de.bstly.board.repository.VoteRepository;
@RequestMapping("/debug")
public class DebugController extends BaseController {
private Logger logger = LogManager.getLogger(DebugController.class);
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private LocalUserRepository localUserRepository;
@Autowired
private CommentRepository commentRepository;
@Autowired
private VoteRepository voteRepository;
@Autowired
private EntryManager entryManager;
@Value("${debug.random.users:0}")
private int users;
@Value("${debug.random.minEntries:0}")
private int minEntries;
@Value("${debug.random.maxEntries:10}")
private int maxEntries;
@Value("${debug.random.entryAge:63115200}")
private long entryAge;
@Value("${debug.random.minComments:0}")
private int minComments;
@Value("${debug.random.maxComments:10}")
private int maxComments;
@Value("${debug.random.subCommentsFactor:0.5}")
private double subCommentsFactor;
private float subCommentsFactor;
@Value("${debug.random.subCommentsThresh:0.3}")
private double subCommentsThresh;
private float subCommentsThresh;
@Value("${debug.random.subCommentsDepth:2}")
private int subCommentsDepth;
@Value("${debug.random.minUpvotes:5}")
private int minUpvotes;
@Value("${debug.random.maxUpvotes:10}")
private int maxUpvotes;
@Value("${debug.random.minDownvotes:0}")
private int minDownvotes;
@Value("${debug.random.maxDownvotes:10}")
private int maxDownvotes;
@ -225,9 +205,9 @@ public class DebugController extends BaseController {
* @param depth the depth
* @param userCount the user count
*/
protected void subComments(Long target, Long parent, Instant date, double factor, double thresh,
protected void subComments(Long target, Long parent, Instant date, float factor, float thresh,
int depth, long userCount) {
if (depth < subCommentsDepth && RandomUtils.nextDouble(0, 1) < thresh) {
if (depth < subCommentsDepth && RandomUtils.nextFloat(0, 1) < thresh) {
long numSubComments = RandomUtils.nextLong(0, Math.round(maxComments * factor));
logger.debug("Create "
+ numSubComments
@ -249,8 +229,8 @@ public class DebugController extends BaseController {
logger.trace("Created subComment: '"
+ comment.getId()
+ "'");
subComments(target, comment.getId(), comment.getCreated(), factor * 0.5,
thresh * 0.5, depth++, userCount);
subComments(target, comment.getId(), comment.getCreated(), factor * 0.5f,
thresh * 0.5f, depth++, userCount);
}
}
}

View File

@ -39,13 +39,13 @@ 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;
import de.bstly.board.model.EntryStatus;
import de.bstly.board.model.EntryType;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.Types;
import de.bstly.board.model.UserPage;
import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType;
import de.bstly.board.model.support.EntryStatus;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
/**
* The Class EntryController.
@ -68,189 +68,76 @@ public class EntryController extends BaseController {
private UserPageManager userPageManager;
/**
* Fetch by ranking.
* Fetch by user page.
*
* @param name the name
* @param usernameParameter the username parameter
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param dateParameter the date parameter
* @param tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type parameter
* @param gravityParameter the gravity parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping()
public Page<Entry> fetchByRanking(@RequestParam("page") Optional<Integer> pageParameter,
@GetMapping("/{name}")
public Page<Entry> fetchByUserPage(@PathVariable("name") String name,
@RequestParam("user") Optional<String> usernameParameter,
@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("gravity") Optional<Double> gravityParameter,
@RequestParam("gravity") Optional<Float> gravityParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
UserPage userPage = userPageManager.get(usernameParameter.orElse(getCurrentUsername()),
name);
if (userPage == null || usernameParameter.isPresent() && !userPage.isPublicPage()) {
throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
}
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
if (gravityParameter.isPresent() && gravityParameter.get() > 2) {
gravityParameter = Optional.of(2.0);
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByRanking(getCurrentUsername(), filter,
gravityParameter.orElse(getGravity()), pageParameter.orElse(0),
sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
filter.setFixedTags(userPage.getTags());
filter.setFixedExcludedTags(userPage.getExcludedTags());
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
entries.getContent(), ignore);
return entries;
}
Page<Entry> entries = null;
/**
* Fetch by date.
*
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param dateParameter the date parameter
* @param tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/new")
public Page<Entry> fetchByDate(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByDate(getCurrentUsername(), filter,
switch (userPage.getSorting()) {
case TOP:
entries = entryManager.fetchByRanking(getCurrentUsername(), filter, getGravity(),
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
List<String> 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 tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type 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<Entry> fetchByComments(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("gravity") Optional<Double> gravityParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByComments(getCurrentUsername(), filter,
gravityParameter.orElse(getGravity()), pageParameter.orElse(0),
sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
List<String> 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 tagsParameter the tags parameter
* @param excludedTagsParameter the excluded tags parameter
* @param typeParameter the type parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/last")
public Page<Entry> fetchByLast(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("date") Optional<Instant> dateParameter,
@RequestParam("tags") Optional<List<String>> tagsParameter,
@RequestParam("excludedTags") Optional<List<String>> excludedTagsParameter,
@RequestParam("type") Optional<EntryType> typeParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
if (dateParameter.isPresent() && dateParameter.get().isAfter(Instant.now())) {
dateParameter = Optional.of(Instant.now());
}
EntryFilter filter = buildFilter(dateParameter.orElse(null), FlaggedStatus.NORMAL,
tagsParameter.orElse(null), excludedTagsParameter.orElse(null),
typeParameter.orElse(null));
Page<Entry> entries = entryManager.fetchByLastComment(getCurrentUsername(), filter,
break;
case NEW:
entries = entryManager.fetchByDate(getCurrentUsername(), filter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
break;
case HOT:
entries = entryManager.fetchByComments(getCurrentUsername(), filter, getGravity(),
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
break;
case LAST:
entries = entryManager.fetchByLastComment(getCurrentUsername(), filter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
break;
}
if (entries == null) {
throw new EntityResponseStatusException(HttpStatus.BAD_REQUEST);
}
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
@ -305,78 +192,6 @@ public class EntryController extends BaseController {
return entries;
}
/**
* Fetch by user page.
*
* @param name the name
* @param usernameParameter the username parameter
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/userpage/{name}")
public Page<Entry> fetchByUserPage(@PathVariable("name") String name,
@RequestParam("user") Optional<String> usernameParameter,
@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
UserPage userPage = userPageManager.get(usernameParameter.orElse(getCurrentUsername()),
name);
if (userPage == null || usernameParameter.isPresent() && !userPage.isPublicPage()) {
throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
}
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
EntryFilter filter = new EntryFilter();
filter.setEntryType(userPage.getEntryType());
filter.setTags(userPage.getTags());
filter.setExcludedTags(userPage.getExcludedTags());
Page<Entry> entries = null;
switch (userPage.getSorting()) {
case TOP:
entries = entryManager.fetchByRanking(getCurrentUsername(), filter, getGravity(),
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
break;
case NEW:
entries = entryManager.fetchByDate(getCurrentUsername(), filter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
break;
case HOT:
entries = entryManager.fetchByComments(getCurrentUsername(), filter, getGravity(),
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
break;
case LAST:
entries = entryManager.fetchByLastComment(getCurrentUsername(), filter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false));
break;
}
if (entries == null) {
throw new EntityResponseStatusException(HttpStatus.BAD_REQUEST);
}
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
entries.getContent(), ignore);
return entries;
}
/**
* Builds the filter.
*

View File

@ -17,7 +17,7 @@ import de.bstly.board.businesslogic.EntryManager;
import de.bstly.board.businesslogic.FlagManager;
import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.model.Flag;
import de.bstly.board.model.Types;
import de.bstly.board.model.support.Types;
/**
* The Class FlagController.

View File

@ -29,7 +29,7 @@ import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry;
import de.bstly.board.model.LocalUser;
import de.bstly.board.model.Types;
import de.bstly.board.model.support.Types;
/**
* The Class ModerationController.

View File

@ -0,0 +1,115 @@
/**
*
*/
package de.bstly.board.controller;
import java.util.List;
import java.util.Optional;
import org.hibernate.search.engine.search.query.SearchResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
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.CommentManager;
import de.bstly.board.businesslogic.EntryManager;
import de.bstly.board.businesslogic.SearchManager;
import de.bstly.board.businesslogic.SettingsManager;
import de.bstly.board.businesslogic.UserManager;
import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry;
import de.bstly.board.model.support.Types;
/**
* @author _bastler@bstly.de
*
*/
@RestController
@RequestMapping("/search")
public class SearchController extends BaseController {
@Autowired
private SearchManager searchManager;
@Autowired
private SettingsManager settingsManager;
@Autowired
private EntryManager entryManager;
@Autowired
private UserManager userManager;
@Autowired
private CommentManager commentManager;
/**
* Search.
*
* @param searchParameter the search parameter
* @param pageParameter the page parameter
* @param sizeParameter the size parameter
* @param byDateParameter the by date parameter
* @param ascParameter the asc parameter
* @param ignoreParameter the ignore parameter
* @return the page
*/
@PreAuthorize("isAuthenticated()")
@GetMapping
public Page<Object> search(@RequestParam("q") String searchParameter,
@RequestParam("type") Optional<String> typeParameter,
@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("byDate") Optional<Boolean> byDateParameter,
@RequestParam("asc") Optional<Boolean> ascParameter,
@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
sizeParameter = Optional.of(100);
}
String type = typeParameter.orElse(Types.entry.toString());
List<Types> types = Lists.newArrayList();
switch (type) {
case "entry":
types.add(Types.entry);
break;
case "comment":
types.add(Types.comment);
break;
case "all":
types.add(Types.comment);
types.add(Types.entry);
break;
}
SearchResult<Object> result = searchManager.search(types, searchParameter,
pageParameter.orElse(0), sizeParameter.orElse(settingsManager.getPageSize()),
ascParameter.orElse(false), byDateParameter.orElse(false));
Page<Object> objects = new PageImpl<Object>(result.hits(),
PageRequest.of(pageParameter.orElse(0),
sizeParameter.orElse(settingsManager.getPageSize())),
result.total().hitCount());
List<String> ignore = ignoreParameter.orElse(Lists.newArrayList());
for (Object object : objects) {
if (object instanceof Entry) {
entryManager.applyMetadata(getCurrentUsername(),
userManager.getKarma(getCurrentUsername()), (Entry) object, ignore);
} else if (object instanceof Comment) {
commentManager.applyMetadata(getCurrentUsername(), (Comment) object, ignore);
}
}
return objects;
}
}

View File

@ -52,9 +52,13 @@ public class UserPageController extends BaseController {
public Page<UserPage> getUserPages(@RequestParam("page") Optional<Integer> pageParameter,
@RequestParam("size") Optional<Integer> sizeParameter,
@RequestParam("desc") Optional<Boolean> descParameter) {
if (userPageManager.countByUser(getCurrentUsername()) == 0L) {
userPageManager.createDefault(getCurrentUsername());
}
return userPageManager.getByUser(getCurrentUsername(), pageParameter.orElse(0),
sizeParameter.orElse(settingsManager.getPageSize()), "name",
descParameter.orElse(false));
sizeParameter.orElse(settingsManager.getPageSize()), descParameter.orElse(false));
}
/**
@ -83,11 +87,13 @@ public class UserPageController extends BaseController {
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/userpage/{name}")
public UserPage getUserPage(@PathVariable("name") String name) {
UserPage userPage = userPageManager.get(getCurrentUsername(), name);
public UserPage getUserPage(@PathVariable("name") String name,
@RequestParam("user") Optional<String> usernameParameter) {
UserPage userPage = userPageManager.get(usernameParameter.orElse(getCurrentUsername()),
name);
if (userPage == null) {
throw new EntityResponseStatusException(HttpStatus.NOT_FOUND);
if (userPage == null || usernameParameter.isPresent() && !userPage.isPublicPage()) {
throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
}
return userPage;

View File

@ -19,9 +19,9 @@ import de.bstly.board.businesslogic.SettingsManager;
import de.bstly.board.businesslogic.UserManager;
import de.bstly.board.businesslogic.VoteManager;
import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.model.Types;
import de.bstly.board.model.Vote;
import de.bstly.board.model.VoteType;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
/**
* The Class VoteController.

View File

@ -6,8 +6,8 @@ package de.bstly.board.controller.model;
import java.time.Instant;
import java.util.List;
import de.bstly.board.model.EntryType;
import de.bstly.board.model.FlaggedStatus;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.FlaggedStatus;
/**
* The Class EntryFilter.
@ -18,6 +18,8 @@ public class EntryFilter {
private FlaggedStatus flaggedStatus;
private List<String> tags;
private List<String> excludedTags;
private List<String> fixedTags;
private List<String> fixedExcludedTags;
private EntryType entryType;
private String additional;
@ -93,6 +95,34 @@ public class EntryFilter {
this.excludedTags = excludedTags;
}
/**
* @return the fixedTags
*/
public List<String> getFixedTags() {
return fixedTags;
}
/**
* @param fixedTags the fixedTags to set
*/
public void setFixedTags(List<String> fixedTags) {
this.fixedTags = fixedTags;
}
/**
* @return the fixedExcludedTags
*/
public List<String> getFixedExcludedTags() {
return fixedExcludedTags;
}
/**
* @param fixedExcludedTags the fixedExcludedTags to set
*/
public void setFixedExcludedTags(List<String> fixedExcludedTags) {
this.fixedExcludedTags = fixedExcludedTags;
}
/**
* Gets the entry type.
*

View File

@ -10,7 +10,7 @@ import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import de.bstly.board.model.Entry;
import de.bstly.board.model.EntryType;
import de.bstly.board.model.support.EntryType;
/**
* The Class EntryValidator.

View File

@ -18,16 +18,27 @@ import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.search.engine.backend.types.Projectable;
import org.hibernate.search.engine.backend.types.Sortable;
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.ValueBridgeRef;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.KeywordField;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import com.google.common.collect.Maps;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.InstantValueBridge;
import de.bstly.board.model.support.Types;
/**
* The Class Comment.
*/
@Entity
@Table(name = "comments")
@EntityListeners({ AuditingEntityListener.class })
@Indexed
public class Comment {
@Id
@ -37,6 +48,7 @@ public class Comment {
@Column(name = "author", nullable = false)
private String author;
@Column(name = "created", nullable = false)
@KeywordField(name = "created", valueBridge = @ValueBridgeRef(type = InstantValueBridge.class), projectable = Projectable.YES, sortable = Sortable.YES)
private Instant created;
@Column(name = "target", nullable = false)
private Long target;
@ -44,12 +56,15 @@ public class Comment {
private Long parent;
@Lob
@Column(name = "text", nullable = false)
@FullTextField
private String text;
@Enumerated(EnumType.STRING)
@Column(name = "flagged_status", nullable = false, columnDefinition = "varchar(255) default 'NORMAL'")
private FlaggedStatus flaggedStatus;
@Transient
private Map<String, Object> metadata;
@Transient
private final Types type = Types.comment;
/**
* Gets the id.
@ -199,4 +214,11 @@ public class Comment {
this.metadata = metadata;
}
/**
* @return the type
*/
public Types getType() {
return type;
}
}

View File

@ -19,25 +19,41 @@ import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.search.engine.backend.types.Projectable;
import org.hibernate.search.engine.backend.types.Sortable;
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.ValueBridgeRef;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.DocumentId;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.KeywordField;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import com.google.common.collect.Maps;
import de.bstly.board.model.support.EntryStatus;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.InstantValueBridge;
import de.bstly.board.model.support.Types;
/**
* The Class Entry.
*/
@Entity
@Table(name = "entries")
@EntityListeners({ AuditingEntityListener.class })
@Indexed
public class Entry {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
@DocumentId
private Long id;
@Column(name = "author", nullable = false)
private String author;
@Column(name = "created", nullable = false)
@KeywordField(name = "created", valueBridge = @ValueBridgeRef(type = InstantValueBridge.class), projectable = Projectable.YES, sortable = Sortable.YES)
private Instant created;
@Enumerated(EnumType.STRING)
@Column(name = "entry_type", nullable = false)
@ -51,18 +67,22 @@ public class Entry {
@Column(name = "url")
private String url;
@Column(name = "title", nullable = false)
@FullTextField(name = "title")
private String title;
@Lob
@Column(name = "text")
@FullTextField(name = "text")
private String text;
@Transient
private List<String> tags;
@Transient
private Double ranking;
private Float ranking;
@Transient
private Long points;
@Transient
private Map<String, Object> metadata;
@Transient
private final Types type = Types.entry;
/**
* Gets the id.
@ -249,7 +269,7 @@ public class Entry {
*
* @return the ranking
*/
public Double getRanking() {
public Float getRanking() {
return ranking;
}
@ -258,7 +278,7 @@ public class Entry {
*
* @param ranking the new ranking
*/
public void setRanking(Double ranking) {
public void setRanking(Float ranking) {
this.ranking = ranking;
}
@ -301,4 +321,11 @@ public class Entry {
this.metadata = metadata;
}
/**
* @return the type
*/
public Types getType() {
return type;
}
}

View File

@ -13,6 +13,8 @@ import javax.persistence.Table;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import de.bstly.board.model.support.Types;
/**
* The Class Flag.
*/

View File

@ -23,6 +23,8 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.collect.Maps;
import de.bstly.board.model.support.Types;
/**
* The Class LocalUser.
*/
@ -58,6 +60,8 @@ public class LocalUser {
private Map<String, String> settings;
@Transient
private Map<String, Object> metadata;
@Transient
private final Types type = Types.user;
/**
* Gets the username.
@ -242,4 +246,11 @@ public class LocalUser {
this.metadata = metadata;
}
/**
* @return the type
*/
public Types getType() {
return type;
}
}

View File

@ -21,6 +21,9 @@ import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.UserPageSorting;
/**
* The Class UserPage.
*/
@ -40,9 +43,11 @@ public class UserPage {
@Enumerated(EnumType.STRING)
@Column(name = "sorting", nullable = false)
private UserPageSorting sorting;
@Column(name = "indexNumber")
private int index = 99;
@ElementCollection
@LazyCollection(LazyCollectionOption.FALSE)
@CollectionTable(name = "users_page_tags")
@CollectionTable(name = "user_pages_tags")
private List<String> tags;
@ElementCollection
@LazyCollection(LazyCollectionOption.FALSE)
@ -52,6 +57,8 @@ public class UserPage {
private EntryType entryType;
@Column(name = "public", columnDefinition = "boolean default false")
private boolean publicPage;
@Column(name = "divider", columnDefinition = "boolean default false")
private boolean divider;
/**
* Gets the id.
@ -125,6 +132,20 @@ public class UserPage {
this.sorting = sorting;
}
/**
* @return the index
*/
public int getIndex() {
return index;
}
/**
* @param index the index to set
*/
public void setIndex(int index) {
this.index = index;
}
/**
* Gets the tags.
*
@ -197,4 +218,18 @@ public class UserPage {
this.publicPage = publicPage;
}
/**
* @return the divider
*/
public boolean isDivider() {
return divider;
}
/**
* @param divider the divider to set
*/
public void setDivider(boolean divider) {
this.divider = divider;
}
}

View File

@ -13,6 +13,9 @@ import javax.persistence.Table;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import de.bstly.board.model.support.Types;
import de.bstly.board.model.support.VoteType;
/**
* The Class Vote.

View File

@ -1,7 +1,7 @@
/**
*
*/
package de.bstly.board.model;
package de.bstly.board.model.support;
/**
* The Enum EntryStatus.

View File

@ -1,7 +1,7 @@
/**
*
*/
package de.bstly.board.model;
package de.bstly.board.model.support;
/**
* The Enum EntryType.

View File

@ -1,7 +1,7 @@
/**
*
*/
package de.bstly.board.model;
package de.bstly.board.model.support;
/**
* The Enum FlaggedStatus.

View File

@ -0,0 +1,33 @@
/**
*
*/
package de.bstly.board.model.support;
import java.time.Instant;
import org.hibernate.search.mapper.pojo.bridge.ValueBridge;
import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeFromIndexedValueContext;
import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext;
/**
* The Class InstantValueBridge.
*/
public class InstantValueBridge implements ValueBridge<Instant, String> {
/*
* @see org.hibernate.search.mapper.pojo.bridge.ValueBridge#toIndexedValue(java.lang.Object, org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext)
*/
@Override
public String toIndexedValue(Instant value, ValueBridgeToIndexedValueContext context) {
return value.toString();
}
/*
* @see org.hibernate.search.mapper.pojo.bridge.ValueBridge#fromIndexedValue(java.lang.Object, org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeFromIndexedValueContext)
*/
@Override
public Instant fromIndexedValue(String value, ValueBridgeFromIndexedValueContext context) {
return value == null ? null : Instant.parse(value);
}
}

View File

@ -1,7 +1,7 @@
/**
*
*/
package de.bstly.board.model;
package de.bstly.board.model.support;
/**
* The Enum Types.

View File

@ -1,7 +1,7 @@
/**
*
*/
package de.bstly.board.model;
package de.bstly.board.model.support;
/**
* The Enum UserPageSorting.

View File

@ -1,7 +1,7 @@
/**
*
*/
package de.bstly.board.model;
package de.bstly.board.model.support;
/**
* The Enum VoteType.

View File

@ -15,58 +15,4 @@ import de.bstly.board.model.Comment;
@Repository
public interface CommentRepository
extends JpaRepository<Comment, Long>, QuerydslPredicateExecutor<Comment> {
// /**
// * Find all by ranking and parent.
// *
// * @param target the target
// * @param date the date
// * @param gravity the gravity
// * @return the list
// */
// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent IS NULL AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent IS NULL AND comment.created < :date", nativeQuery = true)
// List<Comment> findAllByRankingAndParent(@Param("target") Long target,
// @Param("date") Instant date, @Param("gravity") double gravity);
//
// /**
// * Find all by ranking and parent.
// *
// * @param target the target
// * @param parent the parent
// * @param date the date
// * @param gravity the gravity
// * @return the list
// */
// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent = :parent AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent = :parent AND comment.created < :date", nativeQuery = true)
// List<Comment> findAllByRankingAndParent(@Param("target") Long target,
// @Param("parent") Long parent, @Param("date") Instant date,
// @Param("gravity") double gravity);
//
// /**
// * Find all by ranking and parent.
// *
// * @param target the target
// * @param date the date
// * @param gravity the gravity
// * @param pageable the pageable
// * @return the page
// */
// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent IS NULL AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent IS NULL AND comment.created < :date", nativeQuery = true)
// Page<Comment> findAllByRankingAndParent(@Param("target") Long target,
// @Param("date") Instant date, @Param("gravity") double gravity, Pageable pageable);
//
// /**
// * Find all by ranking and parent.
// *
// * @param target the target
// * @param parent the parent
// * @param date the date
// * @param gravity the gravity
// * @param pageable the pageable
// * @return the page
// */
// @Query(value = "SELECT comment.*, ranked.ranking FROM comments AS comment LEFT JOIN (SELECT comment.id, (IFNULL(upvote.count,0) - IFNULL(downvote.count,0)) / POW(TIMESTAMPDIFF(HOUR, comment.created, :date)+2,:gravity) AS ranking FROM comments AS comment LEFT JOIN (SELECT upvote.target,COUNT(upvote.id) AS count FROM votes as upvote WHERE upvote.type = 0 AND upvote.target_type = 0 GROUP BY upvote.target) AS upvote ON upvote.target = comment.id LEFT JOIN (SELECT downvote.target,COUNT(downvote.id) AS count FROM votes as downvote WHERE downvote.type = 1 GROUP BY downvote.target) AS downvote ON downvote.target = comment.id) as ranked on ranked.id = comment.id WHERE comment.target = :target AND parent = :parent AND comment.created < :date ORDER BY ranked.ranking DESC, comment.created DESC", countQuery = "SELECT count(*) FROM comments as comment WHERE comment.target = :target AND parent = :parent AND comment.created < :date", nativeQuery = true)
// Page<Comment> findAllByRankingAndParent(@Param("target") Long target,
// @Param("parent") Long parent, @Param("date") Instant date,
// @Param("gravity") double gravity, Pageable pageable);
}