Files
Athou_commafeed/src/main/java/com/commafeed/backend/dao/FeedEntryStatusDAO.java

263 lines
9.4 KiB
Java
Raw Normal View History

2013-03-22 20:51:22 +01:00
package com.commafeed.backend.dao;
import java.util.Comparator;
2013-04-09 11:10:26 +02:00
import java.util.Date;
2013-03-30 11:37:57 +01:00
import java.util.List;
2014-08-17 14:16:30 +02:00
import javax.inject.Inject;
import javax.inject.Singleton;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.hibernate.SessionFactory;
import com.commafeed.CommaFeedConfiguration;
import com.commafeed.backend.FixedSizeSortedSet;
2013-05-15 16:01:14 +02:00
import com.commafeed.backend.model.FeedEntry;
2013-03-23 16:17:19 +01:00
import com.commafeed.backend.model.FeedEntryStatus;
2013-10-13 10:49:44 +02:00
import com.commafeed.backend.model.FeedEntryTag;
2013-05-15 16:01:14 +02:00
import com.commafeed.backend.model.FeedSubscription;
2013-07-02 18:07:08 +02:00
import com.commafeed.backend.model.Models;
import com.commafeed.backend.model.QFeedEntry;
import com.commafeed.backend.model.QFeedEntryContent;
import com.commafeed.backend.model.QFeedEntryStatus;
import com.commafeed.backend.model.QFeedEntryTag;
2013-03-23 17:17:27 +01:00
import com.commafeed.backend.model.User;
2013-04-10 10:28:48 +02:00
import com.commafeed.backend.model.UserSettings.ReadingOrder;
import com.commafeed.frontend.model.UnreadCount;
2013-06-20 16:49:18 +02:00
import com.google.common.collect.Iterables;
2013-06-21 09:38:49 +02:00
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
2014-08-15 17:29:58 +02:00
import com.mysema.query.BooleanBuilder;
import com.mysema.query.Tuple;
import com.mysema.query.jpa.hibernate.HibernateQuery;
2013-03-22 20:51:22 +01:00
2014-08-17 14:16:30 +02:00
@Singleton
2013-04-11 20:49:08 +02:00
public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
2013-03-22 20:51:22 +01:00
private FeedEntryDAO feedEntryDAO;
private FeedEntryTagDAO feedEntryTagDAO;
private CommaFeedConfiguration config;
private QFeedEntryStatus status = QFeedEntryStatus.feedEntryStatus;
2014-08-15 17:29:58 +02:00
private QFeedEntry entry = QFeedEntry.feedEntry;
private QFeedEntryContent content = QFeedEntryContent.feedEntryContent;
private QFeedEntryTag entryTag = QFeedEntryTag.feedEntryTag;
2014-08-17 14:16:30 +02:00
@Inject
public FeedEntryStatusDAO(SessionFactory sessionFactory, FeedEntryDAO feedEntryDAO, FeedEntryTagDAO feedEntryTagDAO,
CommaFeedConfiguration config) {
super(sessionFactory);
this.feedEntryDAO = feedEntryDAO;
this.feedEntryTagDAO = feedEntryTagDAO;
this.config = config;
}
2013-07-23 16:19:19 +02:00
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_DESC = new Comparator<FeedEntryStatus>() {
@Override
2013-07-23 16:19:19 +02:00
public int compare(FeedEntryStatus o1, FeedEntryStatus o2) {
CompareToBuilder builder = new CompareToBuilder();
builder.append(o2.getEntryUpdated(), o1.getEntryUpdated());
builder.append(o2.getId(), o1.getId());
return builder.toComparison();
};
};
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_ASC = Ordering.from(STATUS_COMPARATOR_DESC).reverse();
2013-10-13 10:49:44 +02:00
public FeedEntryStatus getStatus(User user, FeedSubscription sub, FeedEntry entry) {
List<FeedEntryStatus> statuses = newQuery().from(status).where(status.entry.eq(entry), status.subscription.eq(sub)).list(status);
FeedEntryStatus status = Iterables.getFirst(statuses, null);
2013-10-13 10:49:44 +02:00
return handleStatus(user, status, sub, entry);
2013-07-23 16:19:19 +02:00
}
2013-10-13 10:49:44 +02:00
private FeedEntryStatus handleStatus(User user, FeedEntryStatus status, FeedSubscription sub, FeedEntry entry) {
if (status == null) {
Date unreadThreshold = config.getApplicationSettings().getUnreadThreshold();
2013-07-25 09:17:33 +02:00
boolean read = unreadThreshold == null ? false : entry.getUpdated().before(unreadThreshold);
2013-10-13 10:49:44 +02:00
status = new FeedEntryStatus(user, sub, entry);
2013-07-23 15:27:56 +02:00
status.setRead(read);
status.setMarkable(!read);
} else {
status.setMarkable(true);
2013-06-21 09:38:49 +02:00
}
return status;
2013-05-22 17:12:01 +02:00
}
2013-10-13 10:49:44 +02:00
private FeedEntryStatus fetchTags(User user, FeedEntryStatus status) {
List<FeedEntryTag> tags = feedEntryTagDAO.findByEntry(user, status.getEntry());
status.setTags(tags);
return status;
}
2013-07-25 09:17:33 +02:00
public List<FeedEntryStatus> findStarred(User user, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent) {
HibernateQuery query = newQuery().from(status).where(status.user.eq(user), status.starred.isTrue());
if (newerThan != null) {
query.where(status.entryInserted.gt(newerThan));
}
if (order == ReadingOrder.asc) {
query.orderBy(status.entryUpdated.asc(), status.id.asc());
} else {
query.orderBy(status.entryUpdated.desc(), status.id.desc());
}
query.offset(offset).limit(limit).setTimeout(config.getApplicationSettings().getQueryTimeout());
2013-04-29 22:37:26 +02:00
List<FeedEntryStatus> statuses = query.list(status);
for (FeedEntryStatus status : statuses) {
2013-10-13 10:49:44 +02:00
status = handleStatus(user, status, status.getSubscription(), status.getEntry());
2014-08-14 08:38:13 +02:00
fetchTags(user, status);
}
return lazyLoadContent(includeContent, statuses);
2013-04-29 22:37:26 +02:00
}
2014-08-15 17:29:58 +02:00
private HibernateQuery buildQuery(User user, FeedSubscription sub, boolean unreadOnly, String keywords, Date newerThan, int offset,
int limit, ReadingOrder order, Date last, String tag) {
2014-08-15 17:29:58 +02:00
HibernateQuery query = newQuery().from(entry).where(entry.feed.eq(sub.getFeed()));
if (keywords != null) {
2014-08-15 17:29:58 +02:00
query.join(entry.content, content);
for (String keyword : StringUtils.split(keywords)) {
2014-08-15 17:29:58 +02:00
BooleanBuilder or = new BooleanBuilder();
or.or(content.content.containsIgnoreCase(keyword));
or.or(content.title.containsIgnoreCase(keyword));
query.where(or);
2013-07-23 15:27:56 +02:00
}
}
2014-08-15 17:29:58 +02:00
query.leftJoin(entry.statuses, status).on(status.subscription.id.eq(sub.getId()));
2013-10-13 10:49:44 +02:00
if (unreadOnly && tag == null) {
2014-08-15 17:29:58 +02:00
BooleanBuilder or = new BooleanBuilder();
or.or(status.read.isNull());
or.or(status.read.isFalse());
query.where(or);
2013-07-23 15:27:56 +02:00
Date unreadThreshold = config.getApplicationSettings().getUnreadThreshold();
2013-07-23 15:27:56 +02:00
if (unreadThreshold != null) {
2014-08-15 17:29:58 +02:00
query.where(entry.updated.goe(unreadThreshold));
2013-07-23 15:27:56 +02:00
}
}
2013-10-13 10:49:44 +02:00
if (tag != null) {
2014-08-15 17:29:58 +02:00
BooleanBuilder and = new BooleanBuilder();
and.and(entryTag.user.id.eq(user.getId()));
and.and(entryTag.name.eq(tag));
query.join(entry.tags, entryTag).on(and);
2013-10-13 10:49:44 +02:00
}
if (newerThan != null) {
2014-08-15 17:29:58 +02:00
query.where(entry.inserted.goe(newerThan));
}
if (last != null) {
if (order == ReadingOrder.desc) {
2014-08-15 17:29:58 +02:00
query.where(entry.updated.gt(last));
} else {
2014-08-15 17:29:58 +02:00
query.where(entry.updated.lt(last));
}
}
if (order != null) {
if (order == ReadingOrder.asc) {
2014-08-15 17:29:58 +02:00
query.orderBy(entry.updated.asc(), entry.id.asc());
} else {
2014-08-15 17:29:58 +02:00
query.orderBy(entry.updated.desc(), entry.id.desc());
}
}
if (offset > -1) {
2014-08-15 17:29:58 +02:00
query.offset(offset);
}
if (limit > -1) {
2014-08-15 17:29:58 +02:00
query.limit(limit);
}
int timeout = config.getApplicationSettings().getQueryTimeout();
if (timeout > 0) {
query.setTimeout(timeout / 1000);
}
2014-08-15 17:29:58 +02:00
return query;
}
2013-10-13 10:49:44 +02:00
public List<FeedEntryStatus> findBySubscriptions(User user, List<FeedSubscription> subs, boolean unreadOnly, String keywords,
Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent, boolean onlyIds, String tag) {
int capacity = offset + limit;
2013-07-25 09:17:33 +02:00
Comparator<FeedEntryStatus> comparator = order == ReadingOrder.desc ? STATUS_COMPARATOR_DESC : STATUS_COMPARATOR_ASC;
FixedSizeSortedSet<FeedEntryStatus> set = new FixedSizeSortedSet<FeedEntryStatus>(capacity, comparator);
2013-08-09 12:53:21 +02:00
for (FeedSubscription sub : subs) {
2013-07-25 09:17:33 +02:00
Date last = (order != null && set.isFull()) ? set.last().getEntryUpdated() : null;
2014-08-15 17:29:58 +02:00
HibernateQuery query = buildQuery(user, sub, unreadOnly, keywords, newerThan, -1, capacity, order, last, tag);
List<Tuple> tuples = query.list(entry.id, entry.updated, status.id);
for (Tuple tuple : tuples) {
Long id = tuple.get(entry.id);
Date updated = tuple.get(entry.updated);
Long statusId = tuple.get(status.id);
2013-07-23 16:19:19 +02:00
2013-08-06 12:39:12 +02:00
FeedEntry entry = new FeedEntry();
entry.setId(id);
entry.setUpdated(updated);
2013-07-23 16:19:19 +02:00
2013-08-06 12:39:12 +02:00
FeedEntryStatus status = new FeedEntryStatus();
status.setId(statusId);
2013-08-06 12:39:12 +02:00
status.setEntryUpdated(updated);
2013-07-23 16:19:19 +02:00
status.setEntry(entry);
2013-08-06 12:39:12 +02:00
status.setSubscription(sub);
2013-07-23 16:19:19 +02:00
set.add(status);
}
2013-06-20 18:45:58 +02:00
}
2013-08-12 10:03:34 +02:00
List<FeedEntryStatus> placeholders = set.asList();
int size = placeholders.size();
if (size < offset) {
return Lists.newArrayList();
2013-06-20 18:45:58 +02:00
}
2013-08-12 10:03:34 +02:00
placeholders = placeholders.subList(Math.max(offset, 0), size);
2013-06-20 18:45:58 +02:00
2013-08-12 10:03:34 +02:00
List<FeedEntryStatus> statuses = null;
if (onlyIds) {
statuses = placeholders;
} else {
statuses = Lists.newArrayList();
for (FeedEntryStatus placeholder : placeholders) {
Long statusId = placeholder.getId();
FeedEntry entry = feedEntryDAO.findById(placeholder.getEntry().getId());
2013-10-13 10:49:44 +02:00
FeedEntryStatus status = handleStatus(user, statusId == null ? null : findById(statusId), placeholder.getSubscription(),
entry);
status = fetchTags(user, status);
statuses.add(status);
2013-08-09 12:53:21 +02:00
}
2013-08-12 10:03:34 +02:00
statuses = lazyLoadContent(includeContent, statuses);
2013-08-06 12:39:12 +02:00
}
2013-08-12 10:03:34 +02:00
return statuses;
2013-06-20 18:45:58 +02:00
}
2013-10-13 12:15:41 +02:00
public UnreadCount getUnreadCount(User user, FeedSubscription subscription) {
UnreadCount uc = null;
2014-08-15 17:29:58 +02:00
HibernateQuery query = buildQuery(user, subscription, true, null, null, -1, -1, null, null, null);
List<Tuple> tuples = query.list(entry.count(), entry.updated.max());
for (Tuple tuple : tuples) {
Long count = tuple.get(entry.count());
Date updated = tuple.get(entry.updated.max());
uc = new UnreadCount(subscription.getId(), count, updated);
2013-07-19 12:18:10 +02:00
}
return uc;
2013-07-19 12:18:10 +02:00
}
2013-07-25 09:17:33 +02:00
private List<FeedEntryStatus> lazyLoadContent(boolean includeContent, List<FeedEntryStatus> results) {
if (includeContent) {
for (FeedEntryStatus status : results) {
2013-07-02 18:07:08 +02:00
Models.initialize(status.getSubscription().getFeed());
Models.initialize(status.getEntry().getContent());
}
}
return results;
2013-04-10 10:28:48 +02:00
}
public List<FeedEntryStatus> getOldStatuses(Date olderThan, int limit) {
return newQuery().from(status).where(status.entryInserted.lt(olderThan), status.starred.isFalse()).limit(limit).list(status);
2013-07-25 11:02:49 +02:00
}
2013-03-22 20:51:22 +01:00
}