package com.commafeed.backend.dao; import java.util.Date; import java.util.List; import java.util.Map; import javax.ejb.Stateless; import javax.inject.Inject; import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.apache.commons.lang.StringUtils; import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.FeedCategory; import com.commafeed.backend.model.FeedEntryStatus; 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.User; import com.commafeed.frontend.utils.ModelFactory.MF; import com.google.api.client.util.Lists; import com.google.api.client.util.Maps; import com.uaihebert.model.EasyCriteria; @Stateless @SuppressWarnings("serial") public class FeedEntryStatusService extends GenericDAO { @Inject FeedCategoryService feedCategoryService; public FeedEntryStatus findById(User user, Long id) { EasyCriteria criteria = createCriteria(); criteria.andEquals(MF.i(proxy().getId()), id); criteria.innerJoinFetch(MF.i(proxy().getSubscription())); criteria.innerJoinFetch(MF.i(proxy().getEntry())); criteria.andJoinEquals(MF.i(proxy().getSubscription()), MF.i(MF.p(FeedSubscription.class).getUser()), user); FeedEntryStatus status = null; try { status = criteria.getSingleResult(); } catch (NoResultException e) { status = null; } return status; } public List getStatusesByKeywords(User user, String keywords) { return getStatusesByKeywords(user, keywords, -1, -1); } public List getStatusesByKeywords(User user, String keywords, int offset, int limit) { String joinedKeywords = StringUtils.join( keywords.toLowerCase().split(" "), "%"); joinedKeywords = "%" + joinedKeywords + "%"; CriteriaQuery query = builder.createQuery(getType()); Root root = query.from(getType()); List predicates = Lists.newArrayList(); predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) .get(FeedSubscription_.user), user)); Predicate content = builder.like( builder.lower(root.get(FeedEntryStatus_.entry).get( FeedEntry_.content)), joinedKeywords); Predicate title = builder.like( builder.lower(root.get(FeedEntryStatus_.entry).get( FeedEntry_.title)), joinedKeywords); predicates.add(builder.or(content, title)); query.where(predicates.toArray(new Predicate[0])); query.orderBy(builder.desc(root.get(FeedEntryStatus_.entry).get( FeedEntry_.updated))); TypedQuery q = em.createQuery(query); if (offset > -1) { q.setFirstResult(offset); } if (limit > -1) { q.setMaxResults(limit); } return q.getResultList(); } public List getStatuses(User user, boolean unreadOnly) { return getStatuses(user, unreadOnly, -1, -1); } public List getStatuses(User user, boolean unreadOnly, int offset, int limit) { CriteriaQuery query = builder.createQuery(getType()); Root root = query.from(getType()); List predicates = Lists.newArrayList(); predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) .get(FeedSubscription_.user), user)); if (unreadOnly) { predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); } query.where(predicates.toArray(new Predicate[0])); query.orderBy(builder.desc(root.get(FeedEntryStatus_.entry).get( FeedEntry_.updated))); TypedQuery q = em.createQuery(query); if (offset > -1) { q.setFirstResult(offset); } if (limit > -1) { q.setMaxResults(limit); } return q.getResultList(); } /** * Map between subscriptionId and unread count */ @SuppressWarnings("rawtypes") public Map getUnreadCount(User user) { Map map = Maps.newHashMap(); Query query = em.createNamedQuery("EntryStatus.unreadCounts"); query.setParameter("user", user); List resultList = query.getResultList(); for (Object o : resultList) { Object[] array = (Object[]) o; map.put((Long) array[0], (Long) array[1]); } return map; } public List getStatuses(Feed feed, User user, boolean unreadOnly) { return getStatuses(feed, user, unreadOnly, -1, -1); } public List getStatuses(Feed feed, User user, boolean unreadOnly, int offset, int limit) { CriteriaQuery query = builder.createQuery(getType()); Root root = query.from(getType()); List predicates = Lists.newArrayList(); predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) .get(FeedSubscription_.user), user)); predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) .get(FeedSubscription_.feed), feed)); if (unreadOnly) { predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); } query.where(predicates.toArray(new Predicate[0])); query.orderBy(builder.desc(root.get(FeedEntryStatus_.entry).get( FeedEntry_.updated))); TypedQuery q = em.createQuery(query); if (offset > -1) { q.setFirstResult(offset); } if (limit > -1) { q.setMaxResults(limit); } return q.getResultList(); } public List getStatuses(List categories, User user, boolean unreadOnly) { return getStatuses(categories, user, unreadOnly, -1, -1); } public List getStatuses(List categories, User user, boolean unreadOnly, int offset, int limit) { CriteriaQuery query = builder.createQuery(getType()); Root root = query.from(getType()); List predicates = Lists.newArrayList(); predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) .get(FeedSubscription_.user), user)); predicates.add(root.get(FeedEntryStatus_.subscription) .get(FeedSubscription_.category).in(categories)); if (unreadOnly) { predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); } query.where(predicates.toArray(new Predicate[0])); query.orderBy(builder.desc(root.get(FeedEntryStatus_.entry).get( FeedEntry_.updated))); TypedQuery q = em.createQuery(query); if (offset > -1) { q.setFirstResult(offset); } if (limit > -1) { q.setMaxResults(limit); } return q.getResultList(); } public void markFeedEntries(User user, Feed feed, Date olderThan) { List statuses = getStatuses(feed, user, true); update(markList(statuses, olderThan)); } public void markCategoryEntries(User user, List categories, Date olderThan) { List statuses = getStatuses(categories, user, true); update(markList(statuses, olderThan)); } public void markAllEntries(User user, Date olderThan) { List statuses = getStatuses(user, true); update(markList(statuses, olderThan)); } private List markList(List statuses, Date olderThan) { List list = Lists.newArrayList(); for (FeedEntryStatus status : statuses) { if (!status.isRead()) { Date inserted = status.getEntry().getInserted(); if (olderThan == null || inserted == null || olderThan.after(inserted)) { status.setRead(true); list.add(status); } } } return list; } }