diff --git a/pom.xml b/pom.xml index 62896c49..f6b8fddc 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,17 @@ .css + + org.hibernate:hibernate-entitymanager:4.1.10.Final + org.hibernate:hibernate-core:4.1.10.Final + org.hibernate.common:hibernate-commons-annotations:4.0.1.Final + org.hibernate:hibernate-validator:4.3.1.Final + org.jboss.logging:jboss-logging:3.1.3.GA + dom4j:dom4j:1.6.1 + antlr:antlr:2.7.7 + remove:hsqldb + org.hsqldb:hsqldb:SNAPSHOT + @@ -82,6 +93,12 @@ pom provided + + org.hibernate + hibernate-entitymanager + 4.1.10.Final + provided + uaihebert.com EasyCriteria @@ -211,6 +228,16 @@ true + + hsqldb.snapshots + http://www.hsqldb.org/repos/ + + false + + + true + + diff --git a/src/main/java/com/commafeed/backend/dao/FeedEntryService.java b/src/main/java/com/commafeed/backend/dao/FeedEntryService.java index 5921d650..59a7f333 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedEntryService.java +++ b/src/main/java/com/commafeed/backend/dao/FeedEntryService.java @@ -6,6 +6,7 @@ import java.util.List; import javax.ejb.Stateless; import javax.inject.Inject; +import javax.persistence.Query; import javax.persistence.TypedQuery; import org.apache.commons.lang.StringUtils; @@ -13,7 +14,9 @@ import org.apache.commons.lang.StringUtils; import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.FeedCategory; import com.commafeed.backend.model.FeedEntry; +import com.commafeed.backend.model.FeedEntryStatus; import com.commafeed.backend.model.User; +import com.commafeed.backend.model.extended.FeedEntryWithStatus; import com.commafeed.frontend.utils.ModelFactory.MF; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -62,47 +65,48 @@ public class FeedEntryService extends GenericDAO { return query.getResultList(); } - public List getEntries(Feed feed, User user, boolean read) { - return getEntries(feed, user, read, -1, -1); + public List getEntries(Feed feed, User user, + boolean unreadOnly) { + return getEntries(feed, user, unreadOnly, -1, -1); } - public List getEntries(Feed feed, User user, boolean read, - int offset, int limit) { + public List getEntries(Feed feed, User user, + boolean unreadOnly, int offset, int limit) { String queryName = null; - if (read) { - queryName = "Entry.readByFeed"; - } else { + if (unreadOnly) { queryName = "Entry.unreadByFeed"; - } - TypedQuery query = em.createNamedQuery(queryName, - FeedEntry.class); - query.setParameter("feed", feed); - query.setParameter("user", user); - if (offset > -1) { - query.setFirstResult(offset); - } - if (limit > -1) { - query.setMaxResults(limit); - } - return query.getResultList(); - } - - public List getEntries(List categories, User user, - boolean read) { - return getEntries(categories, user, read, -1, -1); - } - - public List getEntries(List categories, User user, - boolean read, int offset, int limit) { - String queryName = null; - if (read) { - queryName = "Entry.readByCategories"; } else { - queryName = "Entry.unreadByCategories"; + queryName = "Entry.allByFeed"; } - TypedQuery query = em.createNamedQuery(queryName, - FeedEntry.class); + Query query = em.createNamedQuery(queryName); + query.setParameter("feed", feed); + query.setParameter("userId", user.getId()); + if (offset > -1) { + query.setFirstResult(offset); + } + if (limit > -1) { + query.setMaxResults(limit); + } + + return buildList(query.getResultList()); + } + + public List getEntries(List categories, User user, + boolean unreadOnly) { + return getEntries(categories, user, unreadOnly, -1, -1); + } + + public List getEntries(List categories, User user, + boolean unreadOnly, int offset, int limit) { + String queryName = null; + if (unreadOnly) { + queryName = "Entry.unreadByCategories"; + } else { + queryName = "Entry.allByCategories"; + } + Query query = em.createNamedQuery(queryName); query.setParameter("categories", categories); + query.setParameter("userId", user.getId()); query.setParameter("user", user); if (offset > -1) { query.setFirstResult(offset); @@ -110,6 +114,18 @@ public class FeedEntryService extends GenericDAO { if (limit > -1) { query.setMaxResults(limit); } - return query.getResultList(); + return buildList(query.getResultList()); + } + + @SuppressWarnings("rawtypes") + private List buildList(List list){ + List result = Lists.newArrayList(); + for (Object object :list) { + Object[] array = (Object[]) object; + FeedEntry entry = (FeedEntry) array[0]; + FeedEntryStatus status = (FeedEntryStatus) array[1]; + result.add(new FeedEntryWithStatus(entry, status)); + } + return result; } } diff --git a/src/main/java/com/commafeed/backend/model/FeedEntry.java b/src/main/java/com/commafeed/backend/model/FeedEntry.java index 44fbcda7..397e421c 100644 --- a/src/main/java/com/commafeed/backend/model/FeedEntry.java +++ b/src/main/java/com/commafeed/backend/model/FeedEntry.java @@ -1,16 +1,20 @@ package com.commafeed.backend.model; import java.util.Date; +import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Lob; import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import org.apache.commons.codec.binary.StringUtils; + @Entity @Table(name = "FEEDENTRIES") @SuppressWarnings("serial") @@ -26,7 +30,7 @@ public class FeedEntry extends AbstractModel { private String title; @Lob - private String content; + private byte[] content; @Column(length = 2048) private String url; @@ -34,6 +38,9 @@ public class FeedEntry extends AbstractModel { @Temporal(TemporalType.TIMESTAMP) private Date updated; + @OneToMany(mappedBy = "entry") + private Set statuses; + public String getGuid() { return guid; } @@ -51,11 +58,11 @@ public class FeedEntry extends AbstractModel { } public String getContent() { - return content; + return StringUtils.newStringUtf8(content); } public void setContent(String content) { - this.content = content; + this.content = StringUtils.getBytesUtf8(content); } public String getUrl() { @@ -82,4 +89,12 @@ public class FeedEntry extends AbstractModel { this.feed = feed; } + public Set getStatuses() { + return statuses; + } + + public void setStatuses(Set statuses) { + this.statuses = statuses; + } + } diff --git a/src/main/java/com/commafeed/backend/model/extended/FeedEntryWithStatus.java b/src/main/java/com/commafeed/backend/model/extended/FeedEntryWithStatus.java new file mode 100644 index 00000000..b5a14f34 --- /dev/null +++ b/src/main/java/com/commafeed/backend/model/extended/FeedEntryWithStatus.java @@ -0,0 +1,31 @@ +package com.commafeed.backend.model.extended; + +import com.commafeed.backend.model.FeedEntry; +import com.commafeed.backend.model.FeedEntryStatus; + +public class FeedEntryWithStatus { + private FeedEntry entry; + private FeedEntryStatus status; + + public FeedEntryWithStatus(FeedEntry entry, FeedEntryStatus status) { + this.entry = entry; + this.status = status; + } + + public FeedEntry getEntry() { + return entry; + } + + public void setEntry(FeedEntry entry) { + this.entry = entry; + } + + public FeedEntryStatus getStatus() { + return status; + } + + public void setStatus(FeedEntryStatus status) { + this.status = status; + } + +} diff --git a/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java b/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java index df8234dc..e1dfc15a 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java @@ -13,6 +13,7 @@ import com.commafeed.backend.model.FeedCategory; import com.commafeed.backend.model.FeedEntry; import com.commafeed.backend.model.FeedEntryStatus; import com.commafeed.backend.model.FeedSubscription; +import com.commafeed.backend.model.extended.FeedEntryWithStatus; import com.commafeed.frontend.model.Entries; import com.commafeed.frontend.model.Entry; import com.google.common.base.Function; @@ -85,21 +86,12 @@ public class EntriesREST extends AbstractREST { int limit, boolean unreadOnly) { List entries = Lists.newArrayList(); - if (!unreadOnly) { - List unreadEntries = feedEntryService.getEntries( - subscription.getFeed(), getUser(), true, offset, limit); - for (FeedEntry feedEntry : unreadEntries) { - entries.add(populateEntry(buildEntry(feedEntry), subscription, - true)); - } + List unreadEntries = feedEntryService.getEntries( + subscription.getFeed(), getUser(), unreadOnly, offset, limit); + for (FeedEntryWithStatus feedEntry : unreadEntries) { + entries.add(populateEntry(buildEntry(feedEntry), subscription)); } - List readEntries = feedEntryService.getEntries( - subscription.getFeed(), getUser(), false, offset, limit); - for (FeedEntry feedEntry : readEntries) { - entries.add(populateEntry(buildEntry(feedEntry), subscription, - false)); - } return entries; } @@ -108,39 +100,35 @@ public class EntriesREST extends AbstractREST { boolean unreadOnly) { List entries = Lists.newArrayList(); - if (!unreadOnly) { - List unreadEntries = feedEntryService.getEntries( - categories, getUser(), true, offset, limit); - for (FeedEntry feedEntry : unreadEntries) { - entries.add(populateEntry(buildEntry(feedEntry), - subMapping.get(feedEntry.getFeed().getId()), true)); - } + List unreadEntries = feedEntryService.getEntries( + categories, getUser(), unreadOnly, offset, limit); + for (FeedEntryWithStatus feedEntry : unreadEntries) { + entries.add(populateEntry(buildEntry(feedEntry), + subMapping.get(feedEntry.getEntry().getFeed().getId()))); } - List readEntries = feedEntryService.getEntries(categories, - getUser(), false, offset, limit); - for (FeedEntry feedEntry : readEntries) { - entries.add(populateEntry(buildEntry(feedEntry), - subMapping.get(feedEntry.getFeed().getId()), false)); - } return entries; } - private Entry buildEntry(FeedEntry feedEntry) { + private Entry buildEntry(FeedEntryWithStatus feedEntryWithStatus) { Entry entry = new Entry(); + + FeedEntry feedEntry = feedEntryWithStatus.getEntry(); entry.setId(String.valueOf(feedEntry.getId())); entry.setTitle(feedEntry.getTitle()); entry.setContent(feedEntry.getContent()); entry.setDate(feedEntry.getUpdated()); entry.setUrl(feedEntry.getUrl()); + FeedEntryStatus status = feedEntryWithStatus.getStatus(); + entry.setRead(status == null ? false : status.isRead()); + return entry; } - private Entry populateEntry(Entry entry, FeedSubscription sub, boolean read) { + private Entry populateEntry(Entry entry, FeedSubscription sub) { entry.setFeedName(sub.getTitle()); entry.setFeedId(String.valueOf(sub.getId())); - entry.setRead(read); return entry; } @@ -156,16 +144,14 @@ public class EntriesREST extends AbstractREST { FeedEntry entry = feedEntryService.findById(Long.valueOf(id)); markEntry(entry, read); } else if (type == Type.feed) { - List entries = Lists.newArrayList(); Feed feed = feedSubscriptionService.findById(Long.valueOf(id)) .getFeed(); if (read) { - entries.addAll(feedEntryService.getEntries(feed, getUser(), - false)); - } - entries.addAll(feedEntryService.getEntries(feed, getUser(), true)); - for (FeedEntry entry : entries) { - markEntry(entry, read); + List entries = feedEntryService + .getEntries(feed, getUser(), false); + for (FeedEntryWithStatus entry : entries) { + markEntry(entry.getEntry(), true); + } } } } diff --git a/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java b/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java index e0fbc72b..c8237fe1 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java @@ -118,7 +118,7 @@ public class SubscriptionsREST extends AbstractREST { sub.setName(subscription.getTitle()); sub.setMessage(subscription.getFeed().getMessage()); int size = feedEntryService.getEntries(subscription.getFeed(), - getUser(), false).size(); + getUser(), true).size(); sub.setUnread(size); category.getFeeds().add(sub); } diff --git a/src/main/resources/META-INF/orm.xml b/src/main/resources/META-INF/orm.xml index 1f6739bc..2250759b 100644 --- a/src/main/resources/META-INF/orm.xml +++ b/src/main/resources/META-INF/orm.xml @@ -9,16 +9,16 @@ select e from FeedEntry e where e.guid in (:guids) order by e.updated desc - select e from FeedEntry e where e.feed=:feed and not exists (select s from FeedEntryStatus s where s.entry = e and s.user =:user and s.read=true) order by e.updated desc + select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) where e.feed=:feed and not exists (select s2 from FeedEntryStatus s2 where s2.entry=e and s2.user.id=:userId and s2.read=true) order by e.updated desc - - select e from FeedEntry e where e.feed=:feed and exists (select s from FeedEntryStatus s where s.entry = e and s.user =:user and s.read=true) order by e.updated desc + + select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) where e.feed=:feed order by e.updated desc - select e from FeedEntry e where exists (select s from FeedSubscription s where s.user=:user and s.feed = e.feed and s.category in (:categories) ) and not exists (select s from FeedEntryStatus s where s.entry = e and s.user =:user and s.read=true) order by e.updated desc + select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) where exists (select s2 from FeedSubscription s2 where s2.user=:user and s2.feed = e.feed and s2.category in (:categories) ) and not exists (select s3 from FeedEntryStatus s3 where s3.entry = e and s3.user =:user and s3.read=true) order by e.updated desc - - select e from FeedEntry e where exists (select s from FeedSubscription s where s.user=:user and s.feed = e.feed and s.category in (:categories) ) and exists (select s from FeedEntryStatus s where s.entry = e and s.user =:user and s.read=true) order by e.updated desc + + select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) where exists (select s2 from FeedSubscription s2 where s2.user=:user and s2.feed = e.feed and s2.category in (:categories) ) order by e.updated desc \ No newline at end of file diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 2fae8d63..e3d43b06 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -5,6 +5,7 @@ http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> + org.hibernate.ejb.HibernatePersistence ${jpa.datasource.name} diff --git a/src/main/webapp/js/services.js b/src/main/webapp/js/services.js index bd18ac18..6ede7a5c 100644 --- a/src/main/webapp/js/services.js +++ b/src/main/webapp/js/services.js @@ -87,6 +87,8 @@ module.factory('EntryService', [ module.service('SettingsService', function($resource) { var s = {} + s.settings = {}; + s.settings.readMode = 'unread'; s.settings = $resource('rest/settings/get').get(); s.save = function() { $resource('rest/settings/save').save(s.settings);