Merge branch 'master' into tg

This commit is contained in:
Athou
2013-06-08 17:05:35 +02:00
18 changed files with 281 additions and 139 deletions

View File

@@ -162,12 +162,6 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>uaihebert.com</groupId>
<artifactId>EasyCriteria</artifactId>
<version>2.1.0</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>

View File

@@ -4,6 +4,9 @@ import java.util.List;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.ObjectUtils;
@@ -12,39 +15,54 @@ import com.commafeed.backend.model.FeedCategory_;
import com.commafeed.backend.model.User; import com.commafeed.backend.model.User;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.uaihebert.model.EasyCriteria;
@Stateless @Stateless
public class FeedCategoryDAO extends GenericDAO<FeedCategory> { public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
public List<FeedCategory> findAll(User user) { public List<FeedCategory> findAll(User user) {
EasyCriteria<FeedCategory> criteria = createCriteria();
criteria.andEquals(FeedCategory_.user.getName(), user);
criteria.innerJoinFetch(FeedCategory_.user.getName()); CriteriaQuery<FeedCategory> query = builder.createQuery(getType());
return criteria.getResultList(); Root<FeedCategory> root = query.from(getType());
query.where(builder.equal(root.get(FeedCategory_.user), user));
root.fetch(FeedCategory_.user.getName());
return em.createQuery(query).getResultList();
} }
public FeedCategory findById(User user, Long id) { public FeedCategory findById(User user, Long id) {
EasyCriteria<FeedCategory> criteria = createCriteria(); CriteriaQuery<FeedCategory> query = builder.createQuery(getType());
criteria.andEquals(FeedCategory_.user.getName(), user); Root<FeedCategory> root = query.from(getType());
criteria.andEquals(FeedCategory_.id.getName(), id);
return Iterables.getFirst(criteria.getResultList(), null); Predicate p1 = builder.equal(root.get(FeedCategory_.user), user);
Predicate p2 = builder.equal(root.get(FeedCategory_.id), id);
query.where(p1, p2);
return Iterables.getFirst(em.createQuery(query).getResultList(), null);
} }
public FeedCategory findByName(User user, String name, FeedCategory parent) { public FeedCategory findByName(User user, String name, FeedCategory parent) {
EasyCriteria<FeedCategory> criteria = createCriteria(); CriteriaQuery<FeedCategory> query = builder.createQuery(getType());
criteria.andEquals(FeedCategory_.user.getName(), user); Root<FeedCategory> root = query.from(getType());
criteria.andEquals(FeedCategory_.name.getName(), name);
List<Predicate> predicates = Lists.newArrayList();
predicates.add(builder.equal(root.get(FeedCategory_.user), user));
predicates.add(builder.equal(root.get(FeedCategory_.name), name));
if (parent == null) { if (parent == null) {
criteria.andIsNull(FeedCategory_.parent.getName()); predicates.add(builder.isNull(root.get(FeedCategory_.parent)));
} else { } else {
criteria.andEquals(FeedCategory_.parent.getName(), parent); predicates
.add(builder.equal(root.get(FeedCategory_.parent), parent));
} }
query.where(predicates.toArray(new Predicate[0]));
FeedCategory category = null; FeedCategory category = null;
try { try {
category = criteria.getSingleResult(); category = em.createQuery(query).getSingleResult();
} catch (NoResultException e) { } catch (NoResultException e) {
category = null; category = null;
} }
@@ -52,15 +70,22 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
} }
public List<FeedCategory> findByParent(User user, FeedCategory parent) { public List<FeedCategory> findByParent(User user, FeedCategory parent) {
EasyCriteria<FeedCategory> criteria = createCriteria(); CriteriaQuery<FeedCategory> query = builder.createQuery(getType());
criteria.andEquals(FeedCategory_.user.getName(), user); Root<FeedCategory> root = query.from(getType());
List<Predicate> predicates = Lists.newArrayList();
predicates.add(builder.equal(root.get(FeedCategory_.user), user));
if (parent == null) { if (parent == null) {
criteria.andIsNull(FeedCategory_.parent.getName()); predicates.add(builder.isNull(root.get(FeedCategory_.parent)));
} else { } else {
criteria.andEquals(FeedCategory_.parent.getName(), parent); predicates
.add(builder.equal(root.get(FeedCategory_.parent), parent));
} }
return criteria.getResultList(); query.where(predicates.toArray(new Predicate[0]));
return em.createQuery(query).getResultList();
} }
public List<FeedCategory> findAllChildrenCategories(User user, public List<FeedCategory> findAllChildrenCategories(User user,

View File

@@ -7,6 +7,7 @@ import java.util.List;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
@@ -18,7 +19,6 @@ import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.Feed_; import com.commafeed.backend.model.Feed_;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.uaihebert.model.EasyCriteria;
@Stateless @Stateless
public class FeedDAO extends GenericDAO<Feed> { public class FeedDAO extends GenericDAO<Feed> {
@@ -78,13 +78,15 @@ public class FeedDAO extends GenericDAO<Feed> {
} }
public Feed findByIdWithEntries(Long feedId, int offset, int limit) { public Feed findByIdWithEntries(Long feedId, int offset, int limit) {
EasyCriteria<Feed> criteria = createCriteria(); CriteriaQuery<Feed> query = builder.createQuery(getType());
criteria.andEquals(Feed_.id.getName(), feedId); Root<Feed> root = query.from(getType());
criteria.leftJoinFetch(Feed_.entries.getName());
criteria.setFirstResult(offset); query.where(builder.equal(root.get(Feed_.id), feedId));
criteria.setMaxResults(limit); root.fetch(Feed_.entries, JoinType.LEFT);
return criteria.getSingleResult();
TypedQuery<Feed> q = em.createQuery(query);
limit(q, offset, limit);
return q.getSingleResult();
} }
public List<Feed> findByTopic(String topic) { public List<Feed> findByTopic(String topic) {

View File

@@ -10,6 +10,7 @@ import javax.persistence.criteria.Root;
import javax.persistence.criteria.SetJoin; import javax.persistence.criteria.SetJoin;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.hibernate.Hibernate;
import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedEntry; import com.commafeed.backend.model.FeedEntry;
@@ -28,9 +29,13 @@ public class FeedEntryDAO extends GenericDAO<FeedEntry> {
query.distinct(true); query.distinct(true);
query.where(builder.equal(root.get(FeedEntry_.guidHash), hash)); query.where(builder.equal(root.get(FeedEntry_.guidHash), hash));
root.fetch(FeedEntry_.feeds, JoinType.LEFT);
TypedQuery<FeedEntry> q = em.createQuery(query); TypedQuery<FeedEntry> q = em.createQuery(query);
return q.getResultList(); List<FeedEntry> list = q.getResultList();
for (FeedEntry entry : list) {
Hibernate.initialize(entry.getFeeds());
}
return list;
} }
public List<FeedEntry> findByGuids(List<String> guids) { public List<FeedEntry> findByGuids(List<String> guids) {
@@ -45,8 +50,13 @@ public class FeedEntryDAO extends GenericDAO<FeedEntry> {
query.distinct(true); query.distinct(true);
query.where(root.get(FeedEntry_.guidHash).in(hashes)); query.where(root.get(FeedEntry_.guidHash).in(hashes));
root.fetch(FeedEntry_.feeds, JoinType.LEFT); root.fetch(FeedEntry_.feeds, JoinType.LEFT);
TypedQuery<FeedEntry> q = em.createQuery(query); TypedQuery<FeedEntry> q = em.createQuery(query);
return q.getResultList(); List<FeedEntry> list = q.getResultList();
for (FeedEntry entry : list) {
Hibernate.initialize(entry.getFeeds());
}
return list;
} }
public List<FeedEntry> findByFeed(Feed feed, int offset, int limit) { public List<FeedEntry> findByFeed(Feed feed, int offset, int limit) {

View File

@@ -31,23 +31,27 @@ import com.commafeed.backend.model.User;
import com.commafeed.backend.model.UserSettings.ReadingOrder; import com.commafeed.backend.model.UserSettings.ReadingOrder;
import com.google.api.client.util.Lists; import com.google.api.client.util.Lists;
import com.google.api.client.util.Maps; import com.google.api.client.util.Maps;
import com.uaihebert.model.EasyCriteria;
@Stateless @Stateless
public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> { public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
@SuppressWarnings("unchecked")
public FeedEntryStatus findById(User user, Long id) { public FeedEntryStatus findById(User user, Long id) {
EasyCriteria<FeedEntryStatus> criteria = createCriteria(); CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
criteria.andEquals(FeedEntryStatus_.id.getName(), id); Root<FeedEntryStatus> root = query.from(getType());
criteria.innerJoinFetch(FeedEntryStatus_.subscription.getName()); Join<FeedEntryStatus, FeedSubscription> join = (Join<FeedEntryStatus, FeedSubscription>) root
criteria.andJoinEquals(FeedEntryStatus_.subscription.getName(), .fetch(FeedEntryStatus_.subscription);
FeedSubscription_.user.getName(), user);
Predicate p1 = builder.equal(root.get(FeedEntryStatus_.id), id);
Predicate p2 = builder.equal(join.get(FeedSubscription_.user), user);
query.where(p1, p2);
FeedEntryStatus status = null; FeedEntryStatus status = null;
try { try {
status = criteria.getSingleResult(); status = em.createQuery(query).getSingleResult();
} catch (NoResultException e) { } catch (NoResultException e) {
status = null; status = null;
} }
@@ -96,11 +100,11 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
public List<FeedEntryStatus> findStarred(User user, ReadingOrder order, public List<FeedEntryStatus> findStarred(User user, ReadingOrder order,
boolean includeContent) { boolean includeContent) {
return findStarred(user, -1, -1, order, includeContent); return findStarred(user, null, -1, -1, order, includeContent);
} }
public List<FeedEntryStatus> findStarred(User user, int offset, int limit, public List<FeedEntryStatus> findStarred(User user, Date newerThan,
ReadingOrder order, boolean includeContent) { int offset, int limit, ReadingOrder order, boolean includeContent) {
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType()); CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
Root<FeedEntryStatus> root = query.from(getType()); Root<FeedEntryStatus> root = query.from(getType());
@@ -118,6 +122,11 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
predicates.add(builder.equal(root.get(FeedEntryStatus_.starred), true)); predicates.add(builder.equal(root.get(FeedEntryStatus_.starred), true));
query.where(predicates.toArray(new Predicate[0])); query.where(predicates.toArray(new Predicate[0]));
if (newerThan != null) {
predicates.add(builder.greaterThanOrEqualTo(
entryJoin.get(FeedEntry_.inserted), newerThan));
}
orderBy(query, entryJoin, order); orderBy(query, entryJoin, order);
TypedQuery<FeedEntryStatus> q = em.createQuery(query); TypedQuery<FeedEntryStatus> q = em.createQuery(query);
@@ -127,11 +136,12 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
public List<FeedEntryStatus> findAll(User user, boolean unreadOnly, public List<FeedEntryStatus> findAll(User user, boolean unreadOnly,
ReadingOrder order, boolean includeContent) { ReadingOrder order, boolean includeContent) {
return findAll(user, unreadOnly, -1, -1, order, includeContent); return findAll(user, unreadOnly, null, -1, -1, order, includeContent);
} }
public List<FeedEntryStatus> findAll(User user, boolean unreadOnly, public List<FeedEntryStatus> findAll(User user, boolean unreadOnly,
int offset, int limit, ReadingOrder order, boolean includeContent) { Date newerThan, int offset, int limit, ReadingOrder order,
boolean includeContent) {
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType()); CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
Root<FeedEntryStatus> root = query.from(getType()); Root<FeedEntryStatus> root = query.from(getType());
@@ -148,6 +158,11 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read)));
} }
if (newerThan != null) {
predicates.add(builder.greaterThanOrEqualTo(
entryJoin.get(FeedEntry_.inserted), newerThan));
}
query.where(predicates.toArray(new Predicate[0])); query.where(predicates.toArray(new Predicate[0]));
orderBy(query, entryJoin, order); orderBy(query, entryJoin, order);
@@ -158,12 +173,13 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
public List<FeedEntryStatus> findByFeed(Feed feed, User user, public List<FeedEntryStatus> findByFeed(Feed feed, User user,
boolean unreadOnly, ReadingOrder order, boolean includeContent) { boolean unreadOnly, ReadingOrder order, boolean includeContent) {
return findByFeed(feed, user, unreadOnly, -1, -1, order, includeContent); return findByFeed(feed, user, unreadOnly, null, -1, -1, order,
includeContent);
} }
public List<FeedEntryStatus> findByFeed(Feed feed, User user, public List<FeedEntryStatus> findByFeed(Feed feed, User user,
boolean unreadOnly, int offset, int limit, ReadingOrder order, boolean unreadOnly, Date newerThan, int offset, int limit,
boolean includeContent) { ReadingOrder order, boolean includeContent) {
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType()); CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
Root<FeedEntryStatus> root = query.from(getType()); Root<FeedEntryStatus> root = query.from(getType());
@@ -183,6 +199,11 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read)));
} }
if (newerThan != null) {
predicates.add(builder.greaterThanOrEqualTo(
entryJoin.get(FeedEntry_.inserted), newerThan));
}
query.where(predicates.toArray(new Predicate[0])); query.where(predicates.toArray(new Predicate[0]));
orderBy(query, entryJoin, order); orderBy(query, entryJoin, order);
@@ -195,13 +216,14 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
public List<FeedEntryStatus> findByCategories( public List<FeedEntryStatus> findByCategories(
List<FeedCategory> categories, User user, boolean unreadOnly, List<FeedCategory> categories, User user, boolean unreadOnly,
ReadingOrder order, boolean includeContent) { ReadingOrder order, boolean includeContent) {
return findByCategories(categories, user, unreadOnly, -1, -1, order, return findByCategories(categories, user, unreadOnly, null, -1, -1,
includeContent); order, includeContent);
} }
public List<FeedEntryStatus> findByCategories( public List<FeedEntryStatus> findByCategories(
List<FeedCategory> categories, User user, boolean unreadOnly, List<FeedCategory> categories, User user, boolean unreadOnly,
int offset, int limit, ReadingOrder order, boolean includeContent) { Date newerThan, int offset, int limit, ReadingOrder order,
boolean includeContent) {
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType()); CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
Root<FeedEntryStatus> root = query.from(getType()); Root<FeedEntryStatus> root = query.from(getType());
@@ -220,6 +242,11 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read)));
} }
if (newerThan != null) {
predicates.add(builder.greaterThanOrEqualTo(
entryJoin.get(FeedEntry_.inserted), newerThan));
}
query.where(predicates.toArray(new Predicate[0])); query.where(predicates.toArray(new Predicate[0]));
orderBy(query, entryJoin, order); orderBy(query, entryJoin, order);

View File

@@ -3,6 +3,10 @@ package com.commafeed.backend.dao;
import java.util.List; import java.util.List;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedCategory; import com.commafeed.backend.model.FeedCategory;
@@ -10,59 +14,83 @@ import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.model.FeedSubscription_; import com.commafeed.backend.model.FeedSubscription_;
import com.commafeed.backend.model.User; import com.commafeed.backend.model.User;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.uaihebert.factory.EasyCriteriaFactory;
import com.uaihebert.model.EasyCriteria;
@Stateless @Stateless
public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> { public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
public FeedSubscription findById(User user, Long id) { public FeedSubscription findById(User user, Long id) {
EasyCriteria<FeedSubscription> criteria = createCriteria(); CriteriaQuery<FeedSubscription> query = builder.createQuery(getType());
criteria.andEquals(FeedSubscription_.user.getName(), user); Root<FeedSubscription> root = query.from(getType());
criteria.andEquals(FeedSubscription_.id.getName(), id);
criteria.leftJoinFetch(FeedSubscription_.feed.getName()); Predicate p1 = builder.equal(root.get(FeedSubscription_.user), user);
criteria.leftJoinFetch(FeedSubscription_.category.getName()); Predicate p2 = builder.equal(root.get(FeedSubscription_.id), id);
return Iterables.getFirst(criteria.getResultList(), null);
root.fetch(FeedSubscription_.feed, JoinType.LEFT);
root.fetch(FeedSubscription_.category, JoinType.LEFT);
query.where(p1, p2);
return Iterables.getFirst(em.createQuery(query).getResultList(), null);
} }
public List<FeedSubscription> findByFeed(Feed feed) { public List<FeedSubscription> findByFeed(Feed feed) {
EasyCriteria<FeedSubscription> criteria = createCriteria(); return findByField(FeedSubscription_.feed, feed);
criteria.andEquals(FeedSubscription_.feed.getName(), feed);
return criteria.getResultList();
} }
public FeedSubscription findByFeed(User user, Feed feed) { public FeedSubscription findByFeed(User user, Feed feed) {
EasyCriteria<FeedSubscription> criteria = createCriteria();
criteria.andEquals(FeedSubscription_.user.getName(), user); CriteriaQuery<FeedSubscription> query = builder.createQuery(getType());
criteria.andEquals(FeedSubscription_.feed.getName(), feed); Root<FeedSubscription> root = query.from(getType());
return Iterables.getFirst(criteria.getResultList(), null);
Predicate p1 = builder.equal(root.get(FeedSubscription_.user), user);
Predicate p2 = builder.equal(root.get(FeedSubscription_.feed), feed);
root.fetch(FeedSubscription_.feed, JoinType.LEFT);
root.fetch(FeedSubscription_.category, JoinType.LEFT);
query.where(p1, p2);
return Iterables.getFirst(em.createQuery(query).getResultList(), null);
} }
public List<FeedSubscription> findAll(User user) { public List<FeedSubscription> findAll(User user) {
EasyCriteria<FeedSubscription> criteria = createCriteria();
criteria.andEquals(FeedSubscription_.user.getName(), user);
criteria.innerJoinFetch(FeedSubscription_.feed.getName()); CriteriaQuery<FeedSubscription> query = builder.createQuery(getType());
criteria.leftJoinFetch(FeedSubscription_.category.getName()); Root<FeedSubscription> root = query.from(getType());
return criteria.getResultList();
root.fetch(FeedSubscription_.feed, JoinType.LEFT);
root.fetch(FeedSubscription_.category, JoinType.LEFT);
query.where(builder.equal(root.get(FeedSubscription_.user), user));
return em.createQuery(query).getResultList();
} }
public List<FeedSubscription> findByCategory(User user, public List<FeedSubscription> findByCategory(User user,
FeedCategory category) { FeedCategory category) {
EasyCriteria<FeedSubscription> criteria = EasyCriteriaFactory
.createQueryCriteria(em, getType());
criteria.andEquals(FeedSubscription_.user.getName(), user);
criteria.andEquals(FeedSubscription_.category.getName(), category);
return criteria.getResultList();
CriteriaQuery<FeedSubscription> query = builder.createQuery(getType());
Root<FeedSubscription> root = query.from(getType());
Predicate p1 = builder.equal(root.get(FeedSubscription_.user), user);
Predicate p2 = builder.equal(root.get(FeedSubscription_.category),
category);
query.where(p1, p2);
return em.createQuery(query).getResultList();
} }
public List<FeedSubscription> findWithoutCategories(User user) { public List<FeedSubscription> findWithoutCategories(User user) {
EasyCriteria<FeedSubscription> criteria = EasyCriteriaFactory
.createQueryCriteria(em, getType());
criteria.andEquals(FeedSubscription_.user.getName(), user);
criteria.andIsNull(FeedSubscription_.category.getName());
return criteria.getResultList();
CriteriaQuery<FeedSubscription> query = builder.createQuery(getType());
Root<FeedSubscription> root = query.from(getType());
Predicate p1 = builder.equal(root.get(FeedSubscription_.user), user);
Predicate p2 = builder.isNull(root.get(FeedSubscription_.category));
query.where(p1, p2);
return em.createQuery(query).getResultList();
} }
} }

View File

@@ -17,8 +17,6 @@ import org.hibernate.Session;
import com.commafeed.backend.model.AbstractModel; import com.commafeed.backend.model.AbstractModel;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.uaihebert.factory.EasyCriteriaFactory;
import com.uaihebert.model.EasyCriteria;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public abstract class GenericDAO<T extends AbstractModel> { public abstract class GenericDAO<T extends AbstractModel> {
@@ -73,30 +71,36 @@ public abstract class GenericDAO<T extends AbstractModel> {
} }
public List<T> findAll() { public List<T> findAll() {
return EasyCriteriaFactory.createQueryCriteria(em, getType()) CriteriaQuery<T> query = builder.createQuery(getType());
.getResultList(); query.from(getType());
return em.createQuery(query).getResultList();
} }
public List<T> findAll(int startIndex, int count) { public List<T> findAll(int startIndex, int count) {
EasyCriteria<T> criteria = EasyCriteriaFactory.createQueryCriteria(em, CriteriaQuery<T> query = builder.createQuery(getType());
getType()); query.from(getType());
criteria.setMaxResults(count); TypedQuery<T> q = em.createQuery(query);
criteria.setFirstResult(startIndex); q.setMaxResults(count);
return criteria.getResultList(); q.setFirstResult(startIndex);
return q.getResultList();
} }
public List<T> findAll(int startIndex, int count, String orderBy, public List<T> findAll(int startIndex, int count, String orderBy,
boolean asc) { boolean asc) {
EasyCriteria<T> criteria = EasyCriteriaFactory.createQueryCriteria(em,
getType()); CriteriaQuery<T> query = builder.createQuery(getType());
criteria.setMaxResults(count); Root<T> root = query.from(getType());
criteria.setFirstResult(startIndex);
if (asc) { if (asc) {
criteria.orderByAsc(orderBy); query.orderBy(builder.asc(root.get(orderBy)));
} else { } else {
criteria.orderByDesc(orderBy); query.orderBy(builder.desc(root.get(orderBy)));
} }
return criteria.getResultList();
TypedQuery<T> q = em.createQuery(query);
q.setMaxResults(count);
q.setFirstResult(startIndex);
return q.getResultList();
} }
public long getCount() { public long getCount() {
@@ -107,10 +111,12 @@ public abstract class GenericDAO<T extends AbstractModel> {
return em.createQuery(query).getSingleResult(); return em.createQuery(query).getSingleResult();
} }
public <V> List<T> findByField(Attribute<T, V> field, V value) { protected <V> List<T> findByField(Attribute<T, V> field, V value) {
EasyCriteria<T> criteria = createCriteria(); CriteriaQuery<T> query = builder.createQuery(getType());
criteria.andEquals(field.getName(), value); Root<T> root = query.from(getType());
return criteria.getResultList();
query.where(builder.equal(root.get(field.getName()), value));
return em.createQuery(query).getResultList();
} }
protected void limit(TypedQuery<?> query, int offset, int limit) { protected void limit(TypedQuery<?> query, int offset, int limit) {
@@ -126,8 +132,4 @@ public abstract class GenericDAO<T extends AbstractModel> {
protected Class<T> getType() { protected Class<T> getType() {
return (Class<T>) type.getRawType(); return (Class<T>) type.getRawType();
} }
public EasyCriteria<T> createCriteria() {
return EasyCriteriaFactory.createQueryCriteria(em, getType());
}
} }

View File

@@ -4,25 +4,28 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Root;
import com.commafeed.backend.model.User; import com.commafeed.backend.model.User;
import com.commafeed.backend.model.UserRole; import com.commafeed.backend.model.UserRole;
import com.commafeed.backend.model.UserRole.Role; import com.commafeed.backend.model.UserRole.Role;
import com.commafeed.backend.model.UserRole_; import com.commafeed.backend.model.UserRole_;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.uaihebert.factory.EasyCriteriaFactory;
import com.uaihebert.model.EasyCriteria;
@Stateless @Stateless
public class UserRoleDAO extends GenericDAO<UserRole> { public class UserRoleDAO extends GenericDAO<UserRole> {
@Override @Override
public List<UserRole> findAll() { public List<UserRole> findAll() {
EasyCriteria<UserRole> criteria = EasyCriteriaFactory CriteriaQuery<UserRole> query = builder.createQuery(getType());
.createQueryCriteria(em, getType()); Root<UserRole> root = query.from(getType());
criteria.setDistinctTrue(); query.distinct(true);
criteria.leftJoinFetch(UserRole_.user.getName());
return criteria.getResultList(); root.fetch(UserRole_.user, JoinType.LEFT);
return em.createQuery(query).getResultList();
} }
public List<UserRole> findAll(User user) { public List<UserRole> findAll(User user) {

View File

@@ -2,25 +2,26 @@ package com.commafeed.backend.dao;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import com.commafeed.backend.model.User; import com.commafeed.backend.model.User;
import com.commafeed.backend.model.UserSettings; import com.commafeed.backend.model.UserSettings;
import com.commafeed.backend.model.UserSettings_; import com.commafeed.backend.model.UserSettings_;
import com.uaihebert.factory.EasyCriteriaFactory;
import com.uaihebert.model.EasyCriteria;
@Stateless @Stateless
public class UserSettingsDAO extends GenericDAO<UserSettings> { public class UserSettingsDAO extends GenericDAO<UserSettings> {
public UserSettings findByUser(User user) { public UserSettings findByUser(User user) {
EasyCriteria<UserSettings> criteria = EasyCriteriaFactory CriteriaQuery<UserSettings> query = builder.createQuery(getType());
.createQueryCriteria(em, getType()); Root<UserSettings> root = query.from(getType());
criteria.andEquals(UserSettings_.user.getName(), user);
query.where(builder.equal(root.get(UserSettings_.user), user));
UserSettings settings = null; UserSettings settings = null;
try { try {
settings = criteria.getSingleResult(); settings = em.createQuery(query).getSingleResult();
} catch (NoResultException e) { } catch (NoResultException e) {
settings = null; settings = null;
} }

View File

@@ -18,7 +18,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.commafeed.backend.HttpGetter; import com.commafeed.backend.HttpGetter;
import com.commafeed.backend.dao.FeedDAO;
import com.commafeed.backend.feeds.FeedRefreshTaskGiver; import com.commafeed.backend.feeds.FeedRefreshTaskGiver;
import com.commafeed.backend.feeds.FeedUtils; import com.commafeed.backend.feeds.FeedUtils;
import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.Feed;
@@ -39,7 +38,8 @@ public class SubscriptionHandler {
public void subscribe(Feed feed) { public void subscribe(Feed feed) {
try { try {
// make sure the feed has been updated for the callback to work // make sure the feed has been updated in the database so that the
// callback works
Thread.sleep(30000); Thread.sleep(30000);
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
// do nothing // do nothing

View File

@@ -26,9 +26,12 @@ public class Entries implements Serializable {
@ApiProperty("times the server tried to refresh the feed and failed") @ApiProperty("times the server tried to refresh the feed and failed")
private int errorCount; private int errorCount;
@ApiProperty("list generation Timestamp") @ApiProperty("list generation timestamp")
private long timestamp; private long timestamp;
@ApiProperty("if the query has more elements")
private boolean hasMore;
@ApiProperty("list of entries") @ApiProperty("list of entries")
private List<Entry> entries = Lists.newArrayList(); private List<Entry> entries = Lists.newArrayList();
@@ -72,4 +75,12 @@ public class Entries implements Serializable {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public boolean isHasMore() {
return hasMore;
}
public void setHasMore(boolean hasMore) {
this.hasMore = hasMore;
}
} }

View File

@@ -37,6 +37,7 @@ public class Entry implements Serializable {
entry.setEnclosureType(status.getEntry().getContent() entry.setEnclosureType(status.getEntry().getContent()
.getEnclosureType()); .getEnclosureType());
entry.setDate(feedEntry.getUpdated()); entry.setDate(feedEntry.getUpdated());
entry.setInsertedDate(feedEntry.getInserted());
entry.setUrl(feedEntry.getUrl()); entry.setUrl(feedEntry.getUrl());
entry.setRead(status.isRead()); entry.setRead(status.isRead());
@@ -93,6 +94,9 @@ public class Entry implements Serializable {
@ApiProperty("entry publication date") @ApiProperty("entry publication date")
private Date date; private Date date;
@ApiProperty("entry insertion date in the database")
private Date insertedDate;
@ApiProperty("feed id") @ApiProperty("feed id")
private String feedId; private String feedId;
@@ -253,4 +257,12 @@ public class Entry implements Serializable {
this.rtl = rtl; this.rtl = rtl;
} }
public Date getInsertedDate() {
return insertedDate;
}
public void setInsertedDate(Date insertedDate) {
this.insertedDate = insertedDate;
}
} }

View File

@@ -41,7 +41,7 @@ public class NextUnreadRedirectPage extends WebPage {
List<FeedEntryStatus> statuses = null; List<FeedEntryStatus> statuses = null;
if (StringUtils.isBlank(categoryId) if (StringUtils.isBlank(categoryId)
|| CategoryREST.ALL.equals(categoryId)) { || CategoryREST.ALL.equals(categoryId)) {
statuses = feedEntryStatusDAO.findAll(user, true, 0, 1, statuses = feedEntryStatusDAO.findAll(user, true, null, 0, 1,
ReadingOrder.desc, true); ReadingOrder.desc, true);
} else { } else {
FeedCategory category = feedCategoryDAO.findById(user, FeedCategory category = feedCategoryDAO.findById(user,
@@ -50,7 +50,7 @@ public class NextUnreadRedirectPage extends WebPage {
List<FeedCategory> children = feedCategoryDAO List<FeedCategory> children = feedCategoryDAO
.findAllChildrenCategories(user, category); .findAllChildrenCategories(user, category);
statuses = feedEntryStatusDAO.findByCategories(children, user, statuses = feedEntryStatusDAO.findByCategories(children, user,
true, 0, 1, ReadingOrder.desc, false); true, null, 0, 1, ReadingOrder.desc, false);
} }
} }

View File

@@ -65,6 +65,7 @@ public class CategoryREST extends AbstractResourceREST {
public Response getCategoryEntries( public Response getCategoryEntries(
@ApiParam(value = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id, @ApiParam(value = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id,
@ApiParam(value = "all entries or only unread ones", allowableValues = "all,unread", required = true) @QueryParam("readType") ReadType readType, @ApiParam(value = "all entries or only unread ones", allowableValues = "all,unread", required = true) @QueryParam("readType") ReadType readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset, @ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@ApiParam(value = "limit for paging, default 20, maximum 50") @DefaultValue("20") @QueryParam("limit") int limit, @ApiParam(value = "limit for paging, default 20, maximum 50") @DefaultValue("20") @QueryParam("limit") int limit,
@ApiParam(value = "date ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order) { @ApiParam(value = "date ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order) {
@@ -79,10 +80,14 @@ public class CategoryREST extends AbstractResourceREST {
id = ALL; id = ALL;
} }
Date newerThanDate = newerThan == null ? null : new Date(
Long.valueOf(newerThan));
if (ALL.equals(id)) { if (ALL.equals(id)) {
entries.setName("All"); entries.setName("All");
List<FeedEntryStatus> unreadEntries = feedEntryStatusDAO.findAll( List<FeedEntryStatus> unreadEntries = feedEntryStatusDAO.findAll(
getUser(), unreadOnly, offset, limit, order, true); getUser(), unreadOnly, newerThanDate, offset, limit + 1, order,
true);
for (FeedEntryStatus status : unreadEntries) { for (FeedEntryStatus status : unreadEntries) {
entries.getEntries().add( entries.getEntries().add(
Entry.build(status, applicationSettingsService.get() Entry.build(status, applicationSettingsService.get()
@@ -92,7 +97,7 @@ public class CategoryREST extends AbstractResourceREST {
} else if (STARRED.equals(id)) { } else if (STARRED.equals(id)) {
entries.setName("Starred"); entries.setName("Starred");
List<FeedEntryStatus> starred = feedEntryStatusDAO.findStarred( List<FeedEntryStatus> starred = feedEntryStatusDAO.findStarred(
getUser(), offset, limit, order, true); getUser(), newerThanDate, offset, limit + 1, order, true);
for (FeedEntryStatus status : starred) { for (FeedEntryStatus status : starred) {
entries.getEntries().add( entries.getEntries().add(
Entry.build(status, applicationSettingsService.get() Entry.build(status, applicationSettingsService.get()
@@ -106,7 +111,8 @@ public class CategoryREST extends AbstractResourceREST {
.findAllChildrenCategories(getUser(), feedCategory); .findAllChildrenCategories(getUser(), feedCategory);
List<FeedEntryStatus> unreadEntries = feedEntryStatusDAO List<FeedEntryStatus> unreadEntries = feedEntryStatusDAO
.findByCategories(childrenCategories, getUser(), .findByCategories(childrenCategories, getUser(),
unreadOnly, offset, limit, order, true); unreadOnly, newerThanDate, offset, limit + 1,
order, true);
for (FeedEntryStatus status : unreadEntries) { for (FeedEntryStatus status : unreadEntries) {
entries.getEntries().add( entries.getEntries().add(
Entry.build(status, applicationSettingsService Entry.build(status, applicationSettingsService
@@ -116,6 +122,13 @@ public class CategoryREST extends AbstractResourceREST {
} }
} }
boolean hasMore = entries.getEntries().size() > limit;
if (hasMore) {
entries.setHasMore(true);
entries.getEntries().remove(entries.getEntries().size() - 1);
}
entries.setTimestamp(Calendar.getInstance().getTimeInMillis()); entries.setTimestamp(Calendar.getInstance().getTimeInMillis());
return Response.ok(entries).build(); return Response.ok(entries).build();
} }
@@ -135,8 +148,8 @@ public class CategoryREST extends AbstractResourceREST {
int offset = 0; int offset = 0;
int limit = 20; int limit = 20;
Entries entries = (Entries) getCategoryEntries(id, readType, offset, Entries entries = (Entries) getCategoryEntries(id, readType, null,
limit, order).getEntity(); offset, limit, order).getEntity();
SyndFeed feed = new SyndFeedImpl(); SyndFeed feed = new SyndFeedImpl();
feed.setFeedType("rss_2.0"); feed.setFeedType("rss_2.0");

View File

@@ -72,6 +72,7 @@ public class FeedREST extends AbstractResourceREST {
public Response getFeedEntries( public Response getFeedEntries(
@ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id, @ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id,
@ApiParam(value = "all entries or only unread ones", allowableValues = "all,unread", required = true) @QueryParam("readType") ReadType readType, @ApiParam(value = "all entries or only unread ones", allowableValues = "all,unread", required = true) @QueryParam("readType") ReadType readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset, @ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@ApiParam(value = "limit for paging, default 20, maximum 50") @DefaultValue("20") @QueryParam("limit") int limit, @ApiParam(value = "limit for paging, default 20, maximum 50") @DefaultValue("20") @QueryParam("limit") int limit,
@ApiParam(value = "date ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order) { @ApiParam(value = "date ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order) {
@@ -85,6 +86,9 @@ public class FeedREST extends AbstractResourceREST {
Entries entries = new Entries(); Entries entries = new Entries();
boolean unreadOnly = readType == ReadType.unread; boolean unreadOnly = readType == ReadType.unread;
Date newerThanDate = newerThan == null ? null : new Date(
Long.valueOf(newerThan));
FeedSubscription subscription = feedSubscriptionDAO.findById(getUser(), FeedSubscription subscription = feedSubscriptionDAO.findById(getUser(),
Long.valueOf(id)); Long.valueOf(id));
if (subscription != null) { if (subscription != null) {
@@ -94,12 +98,18 @@ public class FeedREST extends AbstractResourceREST {
List<FeedEntryStatus> unreadEntries = feedEntryStatusDAO List<FeedEntryStatus> unreadEntries = feedEntryStatusDAO
.findByFeed(subscription.getFeed(), getUser(), unreadOnly, .findByFeed(subscription.getFeed(), getUser(), unreadOnly,
offset, limit, order, true); newerThanDate, offset, limit + 1, order, true);
for (FeedEntryStatus status : unreadEntries) { for (FeedEntryStatus status : unreadEntries) {
entries.getEntries().add( entries.getEntries().add(
Entry.build(status, applicationSettingsService.get() Entry.build(status, applicationSettingsService.get()
.getPublicUrl())); .getPublicUrl()));
} }
boolean hasMore = entries.getEntries().size() > limit;
if (hasMore) {
entries.setHasMore(true);
entries.getEntries().remove(entries.getEntries().size() - 1);
}
} }
entries.setTimestamp(Calendar.getInstance().getTimeInMillis()); entries.setTimestamp(Calendar.getInstance().getTimeInMillis());
@@ -121,8 +131,8 @@ public class FeedREST extends AbstractResourceREST {
int offset = 0; int offset = 0;
int limit = 20; int limit = 20;
Entries entries = (Entries) getFeedEntries(id, readType, offset, limit, Entries entries = (Entries) getFeedEntries(id, readType, null, offset,
order).getEntity(); limit, order).getEntity();
SyndFeed feed = new SyndFeedImpl(); SyndFeed feed = new SyndFeedImpl();
feed.setFeedType("rss_2.0"); feed.setFeedType("rss_2.0");

View File

@@ -68,7 +68,7 @@ details.feed_details=Szczegóły kanału
details.url=URL details.url=URL
details.name=Nazwa details.name=Nazwa
details.category=Kategoria details.category=Kategoria
details.position=Position ####### Needs translation details.position=Pozycja
details.last_refresh=Ostatnio odświeżony details.last_refresh=Ostatnio odświeżony
details.next_refresh=Następne odświeżenie details.next_refresh=Następne odświeżenie
details.queued_for_refresh=W kolejce do odświeżenia details.queued_for_refresh=W kolejce do odświeżenia

View File

@@ -1,5 +1,6 @@
log4j.logger.com.commafeed=INFO, CONSOLE log4j.logger.com.commafeed=INFO, CONSOLE
log4j.logger.org=WARN, CONSOLE log4j.logger.org=WARN, CONSOLE
log4j.logger.com=WARN, CONSOLE
log4j.logger.ro=WARN, CONSOLE log4j.logger.ro=WARN, CONSOLE
log4j.logger.net.sf.ehcache=ALL, CONSOLE log4j.logger.net.sf.ehcache=ALL, CONSOLE
log4j.logger.org.hibernate.cache=ALL, CONSOLE log4j.logger.org.hibernate.cache=ALL, CONSOLE

View File

@@ -707,7 +707,7 @@ function($scope, $stateParams, $http, $route, $window, EntryService, SettingsSer
$scope.errorCount = data.errorCount; $scope.errorCount = data.errorCount;
$scope.timestamp = data.timestamp; $scope.timestamp = data.timestamp;
$scope.busy = false; $scope.busy = false;
$scope.hasMore = data.entries.length == limit; $scope.hasMore = data.hasMore;
}; };
if (!$scope.keywords) { if (!$scope.keywords) {
var service = $scope.selectedType == 'feed' ? FeedService var service = $scope.selectedType == 'feed' ? FeedService
@@ -933,11 +933,14 @@ function($scope, $stateParams, $http, $route, $window, EntryService, SettingsSer
}); });
Mousetrap.bind('v', function(e) { Mousetrap.bind('v', function(e) {
if ($scope.current) { if ($scope.current) {
$scope.mark($scope.current, true);
window.open($scope.current.url); window.open($scope.current.url);
} }
}); });
Mousetrap.bind('b', function(e) { Mousetrap.bind('b', function(e) {
if ($scope.current) { if ($scope.current) {
$scope.mark($scope.current, true);
var url = $scope.current.url; var url = $scope.current.url;
var a = document.createElement('a'); var a = document.createElement('a');
a.href = url; a.href = url;