mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
major improvement in the way data is stored
This commit is contained in:
@@ -19,7 +19,11 @@ import com.uaihebert.model.EasyCriteria;
|
||||
public class FeedCategoryService extends GenericDAO<FeedCategory> {
|
||||
|
||||
public List<FeedCategory> findAll(User user) {
|
||||
return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user);
|
||||
EasyCriteria<FeedCategory> criteria = createCriteria();
|
||||
criteria.andEquals(MF.i(proxy().getUser()), user);
|
||||
|
||||
criteria.innerJoinFetch(MF.i(proxy().getUser()));
|
||||
return criteria.getResultList();
|
||||
}
|
||||
|
||||
public FeedCategory findById(User user, Long id) {
|
||||
|
||||
@@ -3,27 +3,19 @@ package com.commafeed.backend.dao;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ejb.Stateless;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
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.FeedSubscription;
|
||||
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;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
@Stateless
|
||||
@SuppressWarnings("serial")
|
||||
@@ -36,9 +28,7 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
|
||||
FeedSubscriptionService feedSubscriptionService;
|
||||
|
||||
public void updateEntries(String url, Collection<FeedEntry> entries) {
|
||||
Feed feed = Iterables.getFirst(
|
||||
feedService.findByField(MF.i(MF.p(Feed.class).getUrl()), url),
|
||||
null);
|
||||
Feed feed = feedService.findByUrl(url);
|
||||
List<String> guids = Lists.newArrayList();
|
||||
for (FeedEntry entry : entries) {
|
||||
guids.add(entry.getGuid());
|
||||
@@ -56,7 +46,6 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
|
||||
}
|
||||
if (foundEntry == null) {
|
||||
addFeedToEntry(entry, feed);
|
||||
save(entry);
|
||||
} else {
|
||||
boolean foundFeed = false;
|
||||
for (Feed existingFeed : foundEntry.getFeeds()) {
|
||||
@@ -68,7 +57,6 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
|
||||
|
||||
if (!foundFeed) {
|
||||
addFeedToEntry(foundEntry, feed);
|
||||
update(foundEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,12 +68,13 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
|
||||
|
||||
private void addFeedToEntry(FeedEntry entry, Feed feed) {
|
||||
entry.getFeeds().add(feed);
|
||||
saveOrUpdate(entry);
|
||||
List<FeedSubscription> subscriptions = feedSubscriptionService
|
||||
.findByFeed(feed);
|
||||
for (FeedSubscription sub : subscriptions) {
|
||||
FeedEntryStatus status = new FeedEntryStatus();
|
||||
status.setEntry(entry);
|
||||
status.setUser(sub.getUser());
|
||||
status.setSubscription(sub);
|
||||
em.persist(status);
|
||||
}
|
||||
|
||||
@@ -98,123 +87,4 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
public List<FeedEntryWithStatus> getEntriesByKeywords(User user,
|
||||
String keywords) {
|
||||
return getEntriesByKeywords(user, keywords, -1, -1);
|
||||
}
|
||||
|
||||
public List<FeedEntryWithStatus> getEntriesByKeywords(User user,
|
||||
String keywords, int offset, int limit) {
|
||||
Query query = em.createNamedQuery("Entry.allByKeywords");
|
||||
query.setParameter("userId", user.getId());
|
||||
query.setParameter("user", user);
|
||||
|
||||
String joinedKeywords = StringUtils.join(
|
||||
keywords.toLowerCase().split(" "), "%");
|
||||
query.setParameter("keywords", "%" + joinedKeywords + "%");
|
||||
if (offset > -1) {
|
||||
query.setFirstResult(offset);
|
||||
}
|
||||
if (limit > -1) {
|
||||
query.setMaxResults(limit);
|
||||
}
|
||||
return buildList(query.getResultList());
|
||||
}
|
||||
|
||||
public List<FeedEntryWithStatus> getEntries(User user, boolean unreadOnly) {
|
||||
return getEntries(user, unreadOnly, -1, -1);
|
||||
}
|
||||
|
||||
public List<FeedEntryWithStatus> getEntries(User user, boolean unreadOnly,
|
||||
int offset, int limit) {
|
||||
String queryName = null;
|
||||
if (unreadOnly) {
|
||||
queryName = "Entry.unread";
|
||||
} else {
|
||||
queryName = "Entry.all";
|
||||
}
|
||||
Query query = em.createNamedQuery(queryName);
|
||||
query.setParameter("userId", user.getId());
|
||||
query.setParameter("user", user);
|
||||
if (offset > -1) {
|
||||
query.setFirstResult(offset);
|
||||
}
|
||||
if (limit > -1) {
|
||||
query.setMaxResults(limit);
|
||||
}
|
||||
return buildList(query.getResultList());
|
||||
}
|
||||
|
||||
public Long getUnreadCount(Feed feed, User user) {
|
||||
TypedQuery<Long> query = em.createNamedQuery("Entry.unreadByFeedCount",
|
||||
Long.class);
|
||||
query.setParameter("feed", feed);
|
||||
query.setParameter("userId", user.getId());
|
||||
return query.getSingleResult();
|
||||
}
|
||||
|
||||
public List<FeedEntryWithStatus> getEntries(Feed feed, User user,
|
||||
boolean unreadOnly) {
|
||||
return getEntries(feed, user, unreadOnly, -1, -1);
|
||||
}
|
||||
|
||||
public List<FeedEntryWithStatus> getEntries(Feed feed, User user,
|
||||
boolean unreadOnly, int offset, int limit) {
|
||||
String queryName = null;
|
||||
if (unreadOnly) {
|
||||
queryName = "Entry.unreadByFeed";
|
||||
} else {
|
||||
queryName = "Entry.allByFeed";
|
||||
}
|
||||
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<FeedEntryWithStatus> getEntries(List<FeedCategory> categories,
|
||||
User user, boolean unreadOnly) {
|
||||
return getEntries(categories, user, unreadOnly, -1, -1);
|
||||
}
|
||||
|
||||
public List<FeedEntryWithStatus> getEntries(List<FeedCategory> 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);
|
||||
}
|
||||
if (limit > -1) {
|
||||
query.setMaxResults(limit);
|
||||
}
|
||||
return buildList(query.getResultList());
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private List<FeedEntryWithStatus> buildList(List list) {
|
||||
Set<FeedEntryWithStatus> result = Sets.newLinkedHashSet();
|
||||
for (Object object : list) {
|
||||
Object[] array = (Object[]) object;
|
||||
FeedEntry entry = (FeedEntry) array[0];
|
||||
FeedEntryStatus status = (FeedEntryStatus) array[1];
|
||||
FeedEntryWithStatus fews = new FeedEntryWithStatus(entry, status);
|
||||
result.add(fews);
|
||||
}
|
||||
return Lists.newArrayList(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,172 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
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 com.commafeed.backend.model.FeedEntry;
|
||||
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.User;
|
||||
import com.commafeed.frontend.utils.ModelFactory.MF;
|
||||
import com.uaihebert.factory.EasyCriteriaFactory;
|
||||
import com.uaihebert.model.EasyCriteria;
|
||||
import com.google.api.client.util.Lists;
|
||||
import com.google.api.client.util.Maps;
|
||||
|
||||
@Stateless
|
||||
@SuppressWarnings("serial")
|
||||
public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
|
||||
public List<FeedEntryStatus> findAll(User user) {
|
||||
return findByField(MF.i(proxy().getUser()), user);
|
||||
}
|
||||
@Inject
|
||||
FeedCategoryService feedCategoryService;
|
||||
|
||||
public FeedEntryStatus getStatus(User user, FeedEntry entry) {
|
||||
EasyCriteria<FeedEntryStatus> criteria = EasyCriteriaFactory
|
||||
.createQueryCriteria(em, getType());
|
||||
criteria.andEquals(MF.i(proxy().getUser()), user);
|
||||
criteria.andEquals(MF.i(proxy().getEntry()), entry);
|
||||
public FeedEntryStatus findById(User user, Long id) {
|
||||
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(
|
||||
"EntryStatus.byId", FeedEntryStatus.class);
|
||||
query.setParameter("user", user);
|
||||
query.setParameter("id", id);
|
||||
|
||||
FeedEntryStatus status = null;
|
||||
try {
|
||||
status = criteria.getSingleResult();
|
||||
status = query.getSingleResult();
|
||||
} catch (NoResultException e) {
|
||||
status = null;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatusesByKeywords(User user,
|
||||
String keywords) {
|
||||
return getStatusesByKeywords(user, keywords, -1, -1);
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatusesByKeywords(User user,
|
||||
String keywords, int offset, int limit) {
|
||||
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(
|
||||
"EntryStatus.allByKeywords", FeedEntryStatus.class);
|
||||
query.setParameter("user", user);
|
||||
|
||||
String joinedKeywords = StringUtils.join(
|
||||
keywords.toLowerCase().split(" "), "%");
|
||||
query.setParameter("keywords", "%" + joinedKeywords + "%");
|
||||
if (offset > -1) {
|
||||
query.setFirstResult(offset);
|
||||
}
|
||||
if (limit > -1) {
|
||||
query.setMaxResults(limit);
|
||||
}
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(User user, boolean unreadOnly) {
|
||||
return getStatuses(user, unreadOnly, -1, -1);
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(User user, boolean unreadOnly,
|
||||
int offset, int limit) {
|
||||
String queryName = unreadOnly ? "EntryStatus.unread"
|
||||
: "EntryStatus.all";
|
||||
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(queryName,
|
||||
FeedEntryStatus.class);
|
||||
query.setParameter("user", user);
|
||||
if (offset > -1) {
|
||||
query.setFirstResult(offset);
|
||||
}
|
||||
if (limit > -1) {
|
||||
query.setMaxResults(limit);
|
||||
}
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Map between subscriptionId and unread count
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Map<Long, Long> getUnreadCount(User user) {
|
||||
Map<Long, Long> 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<FeedEntryStatus> getStatuses(Feed feed, User user,
|
||||
boolean unreadOnly) {
|
||||
return getStatuses(feed, user, unreadOnly, -1, -1);
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(Feed feed, User user,
|
||||
boolean unreadOnly, int offset, int limit) {
|
||||
String queryName = unreadOnly ? "EntryStatus.unreadByFeed"
|
||||
: "EntryStatus.allByFeed";
|
||||
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(queryName,
|
||||
FeedEntryStatus.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<FeedEntryStatus> getStatuses(List<FeedCategory> categories,
|
||||
User user, boolean unreadOnly) {
|
||||
return getStatuses(categories, user, unreadOnly, -1, -1);
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(List<FeedCategory> categories,
|
||||
User user, boolean unreadOnly, int offset, int limit) {
|
||||
String queryName = unreadOnly ? "EntryStatus.unreadByCategories"
|
||||
: "EntryStatus.allByCategories";
|
||||
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(queryName,
|
||||
FeedEntryStatus.class);
|
||||
query.setParameter("categories", categories);
|
||||
query.setParameter("user", user);
|
||||
if (offset > -1) {
|
||||
query.setFirstResult(offset);
|
||||
}
|
||||
if (limit > -1) {
|
||||
query.setMaxResults(limit);
|
||||
}
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
public void markFeedEntries(User user, Feed feed) {
|
||||
List<FeedEntryStatus> statuses = getStatuses(feed, user, true);
|
||||
update(markList(statuses));
|
||||
}
|
||||
|
||||
public void markCategoryEntries(User user, List<FeedCategory> categories) {
|
||||
List<FeedEntryStatus> statuses = getStatuses(categories, user, true);
|
||||
update(markList(statuses));
|
||||
}
|
||||
|
||||
public void markAllEntries(User user) {
|
||||
List<FeedEntryStatus> statuses = getStatuses(user, true);
|
||||
update(markList(statuses));
|
||||
}
|
||||
|
||||
private List<FeedEntryStatus> markList(List<FeedEntryStatus> statuses) {
|
||||
List<FeedEntryStatus> list = Lists.newArrayList();
|
||||
for (FeedEntryStatus status : statuses) {
|
||||
if (!status.isRead()) {
|
||||
status.setRead(true);
|
||||
list.add(status);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,13 @@ public class FeedSubscriptionService extends GenericDAO<FeedSubscription> {
|
||||
}
|
||||
|
||||
public List<FeedSubscription> findAll(User user) {
|
||||
return findByField(MF.i(proxy().getUser()), user);
|
||||
EasyCriteria<FeedSubscription> criteria = createCriteria();
|
||||
criteria.andEquals(MF.i(proxy().getUser()), user);
|
||||
|
||||
criteria.innerJoinFetch(MF.i(proxy().getFeed()));
|
||||
criteria.innerJoinFetch(MF.i(proxy().getUser()));
|
||||
criteria.leftJoinFetch(MF.i(proxy().getCategory()));
|
||||
return criteria.getResultList();
|
||||
}
|
||||
|
||||
public List<FeedSubscription> findWithoutCategories(User user) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@@ -37,12 +38,16 @@ public abstract class GenericDAO<T extends AbstractModel> implements
|
||||
em.persist(object);
|
||||
}
|
||||
|
||||
public void update(T... objects) {
|
||||
public void update(List<T> objects) {
|
||||
for (Object object : objects) {
|
||||
em.merge(object);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(T... objects) {
|
||||
update(Arrays.asList(objects));
|
||||
}
|
||||
|
||||
public void saveOrUpdate(AbstractModel m) {
|
||||
if (m.getId() == null) {
|
||||
em.persist(m);
|
||||
|
||||
@@ -13,7 +13,7 @@ public class FeedEntryStatus extends AbstractModel {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(nullable = false)
|
||||
private User user;
|
||||
private FeedSubscription subscription;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(nullable = false)
|
||||
@@ -23,12 +23,12 @@ public class FeedEntryStatus extends AbstractModel {
|
||||
private boolean read;
|
||||
private boolean starred;
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
public FeedSubscription getSubscription() {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
public void setSubscription(FeedSubscription subscription) {
|
||||
this.subscription = subscription;
|
||||
}
|
||||
|
||||
public FeedEntry getEntry() {
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
package com.commafeed.backend.model.extended;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37).append(entry.getId())
|
||||
.append(status == null ? null : status.getId()).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
FeedEntryWithStatus rhs = (FeedEntryWithStatus) obj;
|
||||
return new EqualsBuilder()
|
||||
.append(status == null ? null : status.getId(),
|
||||
rhs.status == null ? null : rhs.status.getId())
|
||||
.append(entry.getId(), rhs.entry.getId()).isEquals();
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public class GoogleImportRedirectPage extends WebPage {
|
||||
builder.addParameter("redirect_uri", redirectUri);
|
||||
builder.addParameter("response_type", "code");
|
||||
builder.addParameter("scope", SCOPE);
|
||||
builder.addParameter("approval_prompt", "force");
|
||||
builder.addParameter("approval_prompt", "auto");
|
||||
builder.addParameter("client_id", clientId);
|
||||
builder.addParameter("state",
|
||||
String.valueOf(CommaFeedSession.get().getUser().getId()));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
@@ -19,6 +18,7 @@ import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.apache.wicket.ThreadContext;
|
||||
import org.apache.wicket.authentication.IAuthenticationStrategy;
|
||||
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
|
||||
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
|
||||
import org.apache.wicket.protocol.http.servlet.ServletWebResponse;
|
||||
import org.apache.wicket.request.cycle.RequestCycle;
|
||||
@@ -94,11 +94,13 @@ public abstract class AbstractREST {
|
||||
CommaFeedSession session = (CommaFeedSession) app
|
||||
.fetchCreateAndSetSession(cycle);
|
||||
|
||||
IAuthenticationStrategy authenticationStrategy = app
|
||||
.getSecuritySettings().getAuthenticationStrategy();
|
||||
String[] data = authenticationStrategy.load();
|
||||
if (data != null && data.length > 1) {
|
||||
session.signIn(data[0], data[1]);
|
||||
if (session.getUser() == null) {
|
||||
IAuthenticationStrategy authenticationStrategy = app
|
||||
.getSecuritySettings().getAuthenticationStrategy();
|
||||
String[] data = authenticationStrategy.load();
|
||||
if (data != null && data.length > 1) {
|
||||
session.signIn(data[0], data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -137,11 +139,10 @@ public abstract class AbstractREST {
|
||||
}
|
||||
|
||||
private boolean checkRole(User user, SecurityCheck annotation) {
|
||||
Set<Role> roles = userRoleService.getRoles(user);
|
||||
if (!roles.contains(annotation.value())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
Roles roles = CommaFeedSession.get().getRoles();
|
||||
boolean authorized = roles.hasAnyRole(new Roles(annotation.value()
|
||||
.name()));
|
||||
return authorized;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -134,7 +134,8 @@ public class AdminUsersREST extends AbstractREST {
|
||||
return Response.status(Status.FORBIDDEN)
|
||||
.entity("You cannot delete the admin user.").build();
|
||||
}
|
||||
feedEntryStatusService.delete(feedEntryStatusService.findAll(user));
|
||||
feedEntryStatusService.delete(feedEntryStatusService.getStatuses(user,
|
||||
false));
|
||||
feedSubscriptionService.delete(feedSubscriptionService.findAll(user));
|
||||
feedCategoryService.delete(feedCategoryService.findAll(user));
|
||||
userSettingsService.delete(userSettingsService.findByUser(user));
|
||||
|
||||
@@ -1,29 +1,25 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
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.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;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
@Path("entries")
|
||||
public class EntriesREST extends AbstractREST {
|
||||
@@ -59,34 +55,37 @@ public class EntriesREST extends AbstractREST {
|
||||
if (subscription != null) {
|
||||
entries.setName(subscription.getTitle());
|
||||
entries.setMessage(subscription.getFeed().getMessage());
|
||||
entries.getEntries().addAll(
|
||||
buildEntries(subscription, offset, limit, unreadOnly));
|
||||
|
||||
List<FeedEntryStatus> unreadEntries = feedEntryStatusService
|
||||
.getStatuses(subscription.getFeed(), getUser(),
|
||||
unreadOnly, offset, limit);
|
||||
for (FeedEntryStatus status : unreadEntries) {
|
||||
entries.getEntries().add(buildEntry(status));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
List<FeedSubscription> subs = feedSubscriptionService
|
||||
.findAll(getUser());
|
||||
Map<Long, FeedSubscription> subMapping = Maps.uniqueIndex(subs,
|
||||
new Function<FeedSubscription, Long>() {
|
||||
public Long apply(FeedSubscription sub) {
|
||||
return sub.getFeed().getId();
|
||||
}
|
||||
});
|
||||
|
||||
if (ALL.equals(id)) {
|
||||
entries.setName("All");
|
||||
entries.getEntries().addAll(
|
||||
buildEntries(subMapping, offset, limit, unreadOnly));
|
||||
List<FeedEntryStatus> unreadEntries = feedEntryStatusService
|
||||
.getStatuses(getUser(), unreadOnly, offset, limit);
|
||||
for (FeedEntryStatus status : unreadEntries) {
|
||||
entries.getEntries().add(buildEntry(status));
|
||||
}
|
||||
|
||||
} else {
|
||||
FeedCategory feedCategory = feedCategoryService.findById(
|
||||
getUser(), Long.valueOf(id));
|
||||
if (feedCategory != null) {
|
||||
List<FeedCategory> childrenCategories = feedCategoryService
|
||||
.findAllChildrenCategories(getUser(), feedCategory);
|
||||
entries.getEntries().addAll(
|
||||
buildEntries(childrenCategories, subMapping,
|
||||
offset, limit, unreadOnly));
|
||||
List<FeedEntryStatus> unreadEntries = feedEntryStatusService
|
||||
.getStatuses(childrenCategories, getUser(),
|
||||
unreadOnly, offset, limit);
|
||||
for (FeedEntryStatus status : unreadEntries) {
|
||||
entries.getEntries().add(buildEntry(status));
|
||||
}
|
||||
entries.setName(feedCategory.getName());
|
||||
}
|
||||
}
|
||||
@@ -96,79 +95,21 @@ public class EntriesREST extends AbstractREST {
|
||||
return entries;
|
||||
}
|
||||
|
||||
private List<Entry> buildEntries(Map<Long, FeedSubscription> subMapping,
|
||||
int offset, int limit, boolean unreadOnly) {
|
||||
List<Entry> entries = Lists.newArrayList();
|
||||
|
||||
List<FeedEntryWithStatus> unreadEntries = feedEntryService.getEntries(
|
||||
getUser(), unreadOnly, offset, limit);
|
||||
for (FeedEntryWithStatus feedEntry : unreadEntries) {
|
||||
FeedSubscription sub = null;
|
||||
for (Feed feed : feedEntry.getEntry().getFeeds()) {
|
||||
sub = subMapping.get(feed.getId());
|
||||
if (sub != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
entries.add(populateEntry(buildEntry(feedEntry), sub));
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
private List<Entry> buildEntries(FeedSubscription subscription, int offset,
|
||||
int limit, boolean unreadOnly) {
|
||||
List<Entry> entries = Lists.newArrayList();
|
||||
|
||||
List<FeedEntryWithStatus> unreadEntries = feedEntryService.getEntries(
|
||||
subscription.getFeed(), getUser(), unreadOnly, offset, limit);
|
||||
for (FeedEntryWithStatus feedEntry : unreadEntries) {
|
||||
entries.add(populateEntry(buildEntry(feedEntry), subscription));
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
private List<Entry> buildEntries(List<FeedCategory> categories,
|
||||
Map<Long, FeedSubscription> subMapping, int offset, int limit,
|
||||
boolean unreadOnly) {
|
||||
List<Entry> entries = Lists.newArrayList();
|
||||
|
||||
List<FeedEntryWithStatus> unreadEntries = feedEntryService.getEntries(
|
||||
categories, getUser(), unreadOnly, offset, limit);
|
||||
for (FeedEntryWithStatus feedEntry : unreadEntries) {
|
||||
FeedSubscription sub = null;
|
||||
for (Feed feed : feedEntry.getEntry().getFeeds()) {
|
||||
sub = subMapping.get(feed.getId());
|
||||
if (sub != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
entries.add(populateEntry(buildEntry(feedEntry), sub));
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
private Entry buildEntry(FeedEntryWithStatus feedEntryWithStatus) {
|
||||
private Entry buildEntry(FeedEntryStatus status) {
|
||||
Entry entry = new Entry();
|
||||
|
||||
FeedEntry feedEntry = feedEntryWithStatus.getEntry();
|
||||
entry.setId(String.valueOf(feedEntry.getId()));
|
||||
FeedEntry feedEntry = status.getEntry();
|
||||
entry.setId(String.valueOf(status.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());
|
||||
entry.setRead(status.isRead());
|
||||
|
||||
return entry;
|
||||
}
|
||||
entry.setFeedName(status.getSubscription().getTitle());
|
||||
entry.setFeedId(String.valueOf(status.getSubscription().getId()));
|
||||
|
||||
private Entry populateEntry(Entry entry, FeedSubscription sub) {
|
||||
entry.setFeedName(sub.getTitle());
|
||||
entry.setFeedId(String.valueOf(sub.getId()));
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -181,70 +122,40 @@ public class EntriesREST extends AbstractREST {
|
||||
Preconditions.checkNotNull(read);
|
||||
|
||||
if (type == Type.entry) {
|
||||
FeedEntry entry = feedEntryService.findById(Long.valueOf(id));
|
||||
markEntry(entry, read);
|
||||
FeedEntryStatus status = feedEntryStatusService.findById(getUser(),
|
||||
Long.valueOf(id));
|
||||
status.setRead(read);
|
||||
feedEntryStatusService.update(status);
|
||||
} else if (type == Type.feed) {
|
||||
if (read) {
|
||||
Feed feed = feedSubscriptionService.findById(Long.valueOf(id))
|
||||
.getFeed();
|
||||
List<FeedEntryWithStatus> entries = feedEntryService
|
||||
.getEntries(feed, getUser(), true);
|
||||
for (FeedEntryWithStatus entry : entries) {
|
||||
markEntry(entry, read);
|
||||
}
|
||||
FeedSubscription subscription = feedSubscriptionService
|
||||
.findById(getUser(), Long.valueOf(id));
|
||||
feedEntryStatusService.markFeedEntries(getUser(),
|
||||
subscription.getFeed());
|
||||
} else {
|
||||
return Response.status(Status.FORBIDDEN)
|
||||
.entity("Operation not supported").build();
|
||||
throw new WebApplicationException(Response.status(
|
||||
Status.INTERNAL_SERVER_ERROR).build());
|
||||
}
|
||||
} else if (type == Type.category) {
|
||||
if (read) {
|
||||
List<FeedEntryWithStatus> entries = null;
|
||||
|
||||
if (ALL.equals(id)) {
|
||||
entries = feedEntryService.getEntries(getUser(), true);
|
||||
feedEntryStatusService.markAllEntries(getUser());
|
||||
} else {
|
||||
FeedCategory feedCategory = feedCategoryService.findById(
|
||||
getUser(), Long.valueOf(id));
|
||||
List<FeedCategory> childrenCategories = feedCategoryService
|
||||
.findAllChildrenCategories(getUser(), feedCategory);
|
||||
|
||||
entries = feedEntryService.getEntries(childrenCategories,
|
||||
getUser(), true);
|
||||
}
|
||||
for (FeedEntryWithStatus entry : entries) {
|
||||
markEntry(entry, read);
|
||||
List<FeedCategory> categories = feedCategoryService
|
||||
.findAllChildrenCategories(getUser(),
|
||||
feedCategoryService.findById(getUser(),
|
||||
Long.valueOf(id)));
|
||||
feedEntryStatusService.markCategoryEntries(getUser(),
|
||||
categories);
|
||||
}
|
||||
} else {
|
||||
return Response.status(Status.FORBIDDEN)
|
||||
.entity("Operation not supported").build();
|
||||
throw new WebApplicationException(Response.status(
|
||||
Status.INTERNAL_SERVER_ERROR).build());
|
||||
}
|
||||
}
|
||||
return Response.ok(Status.OK).build();
|
||||
}
|
||||
|
||||
private void markEntry(FeedEntry entry, boolean read) {
|
||||
FeedEntryStatus status = feedEntryStatusService.getStatus(getUser(),
|
||||
entry);
|
||||
if (status == null) {
|
||||
status = new FeedEntryStatus();
|
||||
status.setUser(getUser());
|
||||
status.setEntry(entry);
|
||||
}
|
||||
status.setRead(read);
|
||||
feedEntryStatusService.saveOrUpdate(status);
|
||||
}
|
||||
|
||||
private void markEntry(FeedEntryWithStatus entryWithStatus, boolean read) {
|
||||
FeedEntryStatus status = entryWithStatus.getStatus();
|
||||
if (status == null) {
|
||||
status = new FeedEntryStatus();
|
||||
status.setUser(getUser());
|
||||
status.setEntry(entryWithStatus.getEntry());
|
||||
}
|
||||
status.setRead(read);
|
||||
feedEntryStatusService.saveOrUpdate(status);
|
||||
}
|
||||
|
||||
@Path("search")
|
||||
@GET
|
||||
public Entries searchEntries(@QueryParam("keywords") String keywords) {
|
||||
@@ -252,27 +163,11 @@ public class EntriesREST extends AbstractREST {
|
||||
|
||||
Entries entries = new Entries();
|
||||
|
||||
List<FeedSubscription> subs = feedSubscriptionService
|
||||
.findAll(getUser());
|
||||
Map<Long, FeedSubscription> subMapping = Maps.uniqueIndex(subs,
|
||||
new Function<FeedSubscription, Long>() {
|
||||
public Long apply(FeedSubscription sub) {
|
||||
return sub.getFeed().getId();
|
||||
}
|
||||
});
|
||||
|
||||
List<Entry> list = Lists.newArrayList();
|
||||
List<FeedEntryWithStatus> entriesWithStatus = feedEntryService
|
||||
.getEntriesByKeywords(getUser(), keywords);
|
||||
for (FeedEntryWithStatus feedEntry : entriesWithStatus) {
|
||||
FeedSubscription sub = null;
|
||||
for (Feed feed : feedEntry.getEntry().getFeeds()) {
|
||||
sub = subMapping.get(feed.getId());
|
||||
if (sub != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
list.add(populateEntry(buildEntry(feedEntry), sub));
|
||||
List<FeedEntryStatus> entriesStatus = feedEntryStatusService
|
||||
.getStatusesByKeywords(getUser(), keywords);
|
||||
for (FeedEntryStatus status : entriesStatus) {
|
||||
list.add(buildEntry(status));
|
||||
}
|
||||
|
||||
entries.setName("Search for : " + keywords);
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.commafeed.frontend.rest.resources;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
@@ -164,16 +165,19 @@ public class SubscriptionsREST extends AbstractREST {
|
||||
List<FeedCategory> categories = feedCategoryService.findAll(getUser());
|
||||
List<FeedSubscription> subscriptions = feedSubscriptionService
|
||||
.findAll(getUser());
|
||||
Map<Long, Long> unreadCount = feedEntryStatusService
|
||||
.getUnreadCount(getUser());
|
||||
|
||||
Category root = buildCategory(null, categories, subscriptions);
|
||||
Category root = buildCategory(null, categories, subscriptions,
|
||||
unreadCount);
|
||||
root.setId("all");
|
||||
root.setName("All");
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
Category buildCategory(Long id, List<FeedCategory> categories,
|
||||
List<FeedSubscription> subscriptions) {
|
||||
private Category buildCategory(Long id, List<FeedCategory> categories,
|
||||
List<FeedSubscription> subscriptions, Map<Long, Long> unreadCount) {
|
||||
Category category = new Category();
|
||||
category.setId(String.valueOf(id));
|
||||
category.setExpanded(true);
|
||||
@@ -183,7 +187,7 @@ public class SubscriptionsREST extends AbstractREST {
|
||||
|| (c.getParent() != null && ObjectUtils.equals(c
|
||||
.getParent().getId(), id))) {
|
||||
Category child = buildCategory(c.getId(), categories,
|
||||
subscriptions);
|
||||
subscriptions, unreadCount);
|
||||
child.setId(String.valueOf(c.getId()));
|
||||
child.setName(c.getName());
|
||||
child.setExpanded(!c.isCollapsed());
|
||||
@@ -206,9 +210,8 @@ public class SubscriptionsREST extends AbstractREST {
|
||||
sub.setName(subscription.getTitle());
|
||||
sub.setMessage(subscription.getFeed().getMessage());
|
||||
sub.setFeedUrl(subscription.getFeed().getLink());
|
||||
long size = feedEntryService.getUnreadCount(
|
||||
subscription.getFeed(), getUser());
|
||||
sub.setUnread(size);
|
||||
Long size = unreadCount.get(subscription.getId());
|
||||
sub.setUnread(size == null ? 0 : size);
|
||||
category.getFeeds().add(sub);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,34 +10,39 @@
|
||||
</named-query>
|
||||
|
||||
<named-query name="Entry.byGuids">
|
||||
<query>select DISTINCT e from FeedEntry e LEFT JOIN FETCH e.feeds where e.guid in (:guids) order by e.updated desc</query>
|
||||
<query>select DISTINCT e from FeedEntry e JOIN FETCH e.feeds where e.guid in (:guids)</query>
|
||||
</named-query>
|
||||
|
||||
<named-query name="Entry.unread">
|
||||
<query>select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) LEFT JOIN FETCH e.feeds where exists (select s2 from FeedSubscription s2 where s2.user=:user and s2.feed member of e.feeds) 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</query>
|
||||
</named-query>
|
||||
<named-query name="Entry.all">
|
||||
<query>select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId)LEFT JOIN FETCH e.feeds where exists (select s2 from FeedSubscription s2 where s2.user=:user and s2.feed member of e.feeds) order by e.updated desc</query>
|
||||
<named-query name="EntryStatus.byId">
|
||||
<query>select s from FeedEntryStatus s where s.subscription.user=:user and s.id=:id</query>
|
||||
</named-query>
|
||||
|
||||
<named-query name="Entry.unreadByFeed">
|
||||
<query>select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) LEFT JOIN FETCH e.feeds where :feed member of e.feeds 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</query>
|
||||
<named-query name="EntryStatus.unread">
|
||||
<query>select s from FeedEntryStatus s where s.subscription.user=:user and s.read=false order by s.entry.updated desc</query>
|
||||
</named-query>
|
||||
<named-query name="Entry.unreadByFeedCount">
|
||||
<query>select count(e) from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) where :feed member of e.feeds and not exists (select s2 from FeedEntryStatus s2 where s2.entry=e and s2.user.id=:userId and s2.read=true)</query>
|
||||
</named-query>
|
||||
<named-query name="Entry.allByFeed">
|
||||
<query>select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) LEFT JOIN FETCH e.feeds where :feed member of e.feeds order by e.updated desc</query>
|
||||
<named-query name="EntryStatus.all">
|
||||
<query>select s from FeedEntryStatus s where s.subscription.user=:user order by s.entry.updated desc</query>
|
||||
</named-query>
|
||||
|
||||
<named-query name="Entry.unreadByCategories">
|
||||
<query>select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) LEFT JOIN FETCH e.feeds where exists (select s2 from FeedSubscription s2 where s2.user=:user and s2.feed member of e.feeds 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</query>
|
||||
<named-query name="EntryStatus.unreadByFeed">
|
||||
<query>select s from FeedEntryStatus s where s.subscription.user=:user and s.subscription.feed=:feed and s.read=false order by s.entry.updated desc</query>
|
||||
</named-query>
|
||||
<named-query name="Entry.allByCategories">
|
||||
<query>select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) LEFT JOIN FETCH e.feeds where exists (select s2 from FeedSubscription s2 where s2.user=:user and s2.feed member of e.feeds and s2.category in (:categories) ) order by e.updated desc</query>
|
||||
<named-query name="EntryStatus.unreadCounts">
|
||||
<query>select s.subscription.id, count(s) from FeedEntryStatus s where s.subscription.user=:user and s.read=false group by s.subscription.id</query>
|
||||
</named-query>
|
||||
<named-query name="EntryStatus.allByFeed">
|
||||
<query>select s from FeedEntryStatus s where s.subscription.user=:user and s.subscription.feed=:feed order by s.entry.updated desc</query>
|
||||
</named-query>
|
||||
|
||||
<named-query name="Entry.allByKeywords">
|
||||
<query>select e, s from FeedEntry e LEFT JOIN e.statuses s WITH (s.user.id=:userId) LEFT JOIN FETCH e.feeds where exists (select s2 from FeedSubscription s2 where s2.user=:user and s2.feed member of e.feeds) and (lower(e.content) like :keywords or lower(e.title) like :keywords) order by e.updated desc</query>
|
||||
<named-query name="EntryStatus.unreadByCategories">
|
||||
<query>select s from FeedEntryStatus s where s.subscription.user=:user and s.subscription.category in (:categories) and s.read=false order by s.entry.updated desc</query>
|
||||
</named-query>
|
||||
<named-query name="EntryStatus.allByCategories">
|
||||
<query>select s from FeedEntryStatus s where s.subscription.user=:user and s.subscription.category in (:categories) order by s.entry.updated desc</query>
|
||||
</named-query>
|
||||
|
||||
<named-query name="EntryStatus.allByKeywords">
|
||||
<query>select s from FeedEntryStatus s where s.subscription.user=:user and (lower(s.entry.content) like :keywords or lower(s.entry.title) like :keywords) order by s.entry.updated desc</query>
|
||||
</named-query>
|
||||
|
||||
</entity-mappings>
|
||||
@@ -5,11 +5,12 @@
|
||||
http://java.sun.com/xml/ns/persistence
|
||||
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||
<persistence-unit name="primary">
|
||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||
<jta-data-source>${jpa.datasource.name}</jta-data-source>
|
||||
<properties>
|
||||
<property name="hibernate.hbm2ddl.auto" value="update" />
|
||||
<property name="hibernate.show_sql" value="${jpa.show_sql}" />
|
||||
<property name="hibernate.default_batch_fetch_size" value="100" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
Reference in New Issue
Block a user