diff --git a/src/main/java/com/commafeed/backend/dao/FeedEntryStatusDAO.java b/src/main/java/com/commafeed/backend/dao/FeedEntryStatusDAO.java index 7b17b3a8..7dea7478 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedEntryStatusDAO.java +++ b/src/main/java/com/commafeed/backend/dao/FeedEntryStatusDAO.java @@ -7,16 +7,22 @@ import java.util.Map; import javax.ejb.Stateless; import javax.persistence.NoResultException; import javax.persistence.Query; +import javax.persistence.Tuple; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Join; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import javax.persistence.criteria.Selection; +import javax.persistence.criteria.SetJoin; import org.apache.commons.lang.StringUtils; import org.hibernate.Hibernate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.FeedCategory; import com.commafeed.backend.model.FeedEntry; import com.commafeed.backend.model.FeedEntryContent; @@ -26,14 +32,19 @@ import com.commafeed.backend.model.FeedEntryStatus_; import com.commafeed.backend.model.FeedEntry_; import com.commafeed.backend.model.FeedSubscription; import com.commafeed.backend.model.FeedSubscription_; +import com.commafeed.backend.model.Feed_; import com.commafeed.backend.model.User; import com.commafeed.backend.model.UserSettings.ReadingOrder; import com.google.api.client.util.Lists; import com.google.api.client.util.Maps; +import com.google.common.collect.Iterables; @Stateless public class FeedEntryStatusDAO extends GenericDAO { + private static Logger log = LoggerFactory + .getLogger(FeedEntryStatusDAO.class); + @SuppressWarnings("unchecked") public FeedEntryStatus findById(User user, Long id) { @@ -57,6 +68,21 @@ public class FeedEntryStatusDAO extends GenericDAO { return status; } + public FeedEntryStatus findByEntry(FeedEntry entry, FeedSubscription sub) { + + CriteriaQuery query = builder.createQuery(getType()); + Root root = query.from(getType()); + + Predicate p1 = builder.equal(root.get(FeedEntryStatus_.entry), entry); + Predicate p2 = builder.equal(root.get(FeedEntryStatus_.subscription), + sub); + + query.where(p1, p2); + + List statuses = em.createQuery(query).getResultList(); + return Iterables.getFirst(statuses, null); + } + public List findByKeywords(User user, String keywords, int offset, int limit) { @@ -135,14 +161,63 @@ public class FeedEntryStatusDAO extends GenericDAO { return lazyLoadContent(includeContent, q.getResultList()); } - public List findAll(User user, boolean unreadOnly, - ReadingOrder order, boolean includeContent) { - return findAll(user, unreadOnly, null, -1, -1, order, includeContent); + public List findAll(User user, Date newerThan, int offset, + int limit, ReadingOrder order, boolean includeContent) { + log.info("new findAll"); + + CriteriaQuery query = builder.createTupleQuery(); + Root root = query.from(FeedEntry.class); + + SetJoin feedJoin = root.join(FeedEntry_.feeds); + SetJoin subJoin = feedJoin + .join(Feed_.subscriptions); + + Selection entryAlias = root.alias("entry"); + Selection subAlias = subJoin.alias("subscription"); + query.multiselect(entryAlias, subAlias); + + List predicates = Lists.newArrayList(); + + predicates + .add(builder.equal(subJoin.get(FeedSubscription_.user), user)); + + if (newerThan != null) { + predicates.add(builder.greaterThanOrEqualTo( + root.get(FeedEntry_.inserted), newerThan)); + } + + query.where(predicates.toArray(new Predicate[0])); + orderBy(query, root, order); + + TypedQuery q = em.createQuery(query); + limit(q, offset, limit); + setTimeout(q); + + List list = q.getResultList(); + List results = Lists.newArrayList(); + for (Tuple tuple : list) { + FeedEntry entry = tuple.get(entryAlias); + FeedSubscription subscription = tuple.get(subAlias); + + FeedEntryStatus status = findByEntry(entry, subscription); + if (status == null) { + status = new FeedEntryStatus(); + status.setEntry(entry); + status.setSubscription(subscription); + } + results.add(status); + } + + return lazyLoadContent(includeContent, results); } - public List findAll(User user, boolean unreadOnly, - Date newerThan, int offset, int limit, ReadingOrder order, + public List findAllUnread(User user, ReadingOrder order, boolean includeContent) { + return findAllUnread(user, null, -1, -1, order, includeContent); + } + + public List findAllUnread(User user, Date newerThan, + int offset, int limit, ReadingOrder order, boolean includeContent) { CriteriaQuery query = builder.createQuery(getType()); Root root = query.from(getType()); @@ -155,9 +230,7 @@ public class FeedEntryStatusDAO extends GenericDAO { predicates .add(builder.equal(subJoin.get(FeedSubscription_.user), user)); - if (unreadOnly) { - predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); - } + predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); if (newerThan != null) { predicates.add(builder.greaterThanOrEqualTo( @@ -293,8 +366,8 @@ public class FeedEntryStatusDAO extends GenericDAO { return results; } - private void orderBy(CriteriaQuery query, - Join entryJoin, ReadingOrder order) { + private void orderBy(CriteriaQuery query, Path entryJoin, + ReadingOrder order) { if (order != null) { Path orderPath = entryJoin.get(FeedEntry_.updated); if (order == ReadingOrder.asc) { @@ -329,7 +402,7 @@ public class FeedEntryStatusDAO extends GenericDAO { } public void markAllEntries(User user, Date olderThan) { - List statuses = findAll(user, true, null, false); + List statuses = findAllUnread(user, null, false); saveOrUpdate(markList(statuses, olderThan)); } diff --git a/src/main/java/com/commafeed/frontend/pages/NextUnreadRedirectPage.java b/src/main/java/com/commafeed/frontend/pages/NextUnreadRedirectPage.java index 473a7e71..32feae81 100644 --- a/src/main/java/com/commafeed/frontend/pages/NextUnreadRedirectPage.java +++ b/src/main/java/com/commafeed/frontend/pages/NextUnreadRedirectPage.java @@ -41,7 +41,7 @@ public class NextUnreadRedirectPage extends WebPage { List statuses = null; if (StringUtils.isBlank(categoryId) || CategoryREST.ALL.equals(categoryId)) { - statuses = feedEntryStatusDAO.findAll(user, true, null, 0, 1, + statuses = feedEntryStatusDAO.findAllUnread(user, null, 0, 1, ReadingOrder.desc, true); } else { FeedCategory category = feedCategoryDAO.findById(user, diff --git a/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java b/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java index c268611d..0e144723 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java @@ -79,16 +79,21 @@ public class CategoryREST extends AbstractResourceREST { if (StringUtils.isBlank(id)) { id = ALL; } - + Date newerThanDate = newerThan == null ? null : new Date( Long.valueOf(newerThan)); if (ALL.equals(id)) { entries.setName("All"); - List unreadEntries = feedEntryStatusDAO.findAll( - getUser(), unreadOnly, newerThanDate, offset, limit + 1, order, - true); - for (FeedEntryStatus status : unreadEntries) { + List list = null; + if (unreadOnly) { + list = feedEntryStatusDAO.findAllUnread(getUser(), + newerThanDate, offset, limit + 1, order, true); + } else { + list = feedEntryStatusDAO.findAll(getUser(), newerThanDate, + offset, limit + 1, order, true); + } + for (FeedEntryStatus status : list) { entries.getEntries().add( Entry.build(status, applicationSettingsService.get() .getPublicUrl()));