import OPML

This commit is contained in:
Jeremie Panzer
2013-03-25 12:24:00 +01:00
parent fa18c80e84
commit f0c4733b76
30 changed files with 307 additions and 24 deletions

View File

@@ -3,15 +3,45 @@ package com.commafeed.backend.dao;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.NoResultException;
import com.commafeed.backend.model.FeedCategory;
import com.commafeed.backend.model.User;
import com.commafeed.frontend.utils.ModelFactory.MF;
import com.google.common.collect.Iterables;
import com.uaihebert.model.EasyCriteria;
@Stateless
@SuppressWarnings("serial")
public class FeedCategoryService extends GenericDAO<FeedCategory, Long> {
public List<FeedCategory> findAll(User user) {
return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user);
}
public FeedCategory findById(User user, Long id) {
EasyCriteria<FeedCategory> criteria = createCriteria();
criteria.andEquals(MF.i(proxy().getUser()), user);
criteria.andEquals(MF.i(proxy().getId()), id);
return Iterables.getFirst(criteria.getResultList(), null);
}
public FeedCategory findByName(User user, String name, FeedCategory parent) {
EasyCriteria<FeedCategory> criteria = createCriteria();
criteria.andEquals(MF.i(proxy().getUser()), user);
criteria.andEquals(MF.i(proxy().getName()), name);
if (parent == null) {
criteria.andIsNull(MF.i(proxy().getParent()));
} else {
criteria.andEquals(MF.i(proxy().getParent()), parent);
}
FeedCategory category = null;
try {
category = criteria.getSingleResult();
} catch (NoResultException e) {
category = null;
}
return category;
}
}

View File

@@ -15,6 +15,7 @@ import com.commafeed.frontend.utils.ModelFactory.MF;
import com.google.common.collect.Iterables;
@Stateless
@SuppressWarnings("serial")
public class FeedEntryService extends GenericDAO<FeedEntry, Long> {
@Inject
@@ -34,6 +35,7 @@ public class FeedEntryService extends GenericDAO<FeedEntry, Long> {
}
}
feed.setLastUpdated(Calendar.getInstance().getTime());
feed.setMessage(null);
em.merge(feed);
}
@@ -45,7 +47,7 @@ public class FeedEntryService extends GenericDAO<FeedEntry, Long> {
typedQuery.setParameter("user", user);
return typedQuery.getResultList();
}
public List<FeedEntry> getAllEntries(Feed feed) {
String query = "select e from FeedEntry e where e.feed=:feed";
TypedQuery<FeedEntry> typedQuery = em.createQuery(query,

View File

@@ -11,6 +11,7 @@ import com.uaihebert.factory.EasyCriteriaFactory;
import com.uaihebert.model.EasyCriteria;
@Stateless
@SuppressWarnings("serial")
public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus, Long> {
public FeedEntryStatus getStatus(User user, FeedEntry entry) {

View File

@@ -9,6 +9,7 @@ import com.commafeed.frontend.utils.ModelFactory.MF;
import com.google.common.collect.Iterables;
@Stateless
@SuppressWarnings("serial")
public class FeedService extends GenericDAO<Feed, Long> {
public Feed findByUrl(String url) {

View File

@@ -8,20 +8,37 @@ import javax.persistence.TypedQuery;
import org.apache.commons.lang.ObjectUtils;
import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedCategory;
import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.model.User;
import com.commafeed.frontend.utils.ModelFactory.MF;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.uaihebert.factory.EasyCriteriaFactory;
import com.uaihebert.model.EasyCriteria;
@Stateless
@SuppressWarnings("serial")
public class FeedSubscriptionService extends GenericDAO<FeedSubscription, Long> {
@Inject
FeedCategoryService feedCategoryService;
public FeedSubscription findById(User user, Long id) {
EasyCriteria<FeedSubscription> criteria = createCriteria();
criteria.andEquals(MF.i(proxy().getUser()), user);
criteria.andEquals(MF.i(proxy().getId()), id);
return Iterables.getFirst(criteria.getResultList(), null);
}
public FeedSubscription findByFeed(User user, Feed feed) {
EasyCriteria<FeedSubscription> criteria = createCriteria();
criteria.andEquals(MF.i(proxy().getUser()), user);
criteria.andEquals(MF.i(proxy().getFeed()), feed);
return Iterables.getFirst(criteria.getResultList(), null);
}
public List<FeedSubscription> findAll(User user) {
return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user);
}

View File

@@ -98,6 +98,10 @@ public abstract class GenericDAO<T, K> implements
protected Class<T> getType() {
return (Class<T>) type.getRawType();
}
public EasyCriteria<T> createCriteria(){
return EasyCriteriaFactory.createQueryCriteria(em, getType());
}
protected T proxy() {
return MF.p(getType());

View File

@@ -11,6 +11,7 @@ import com.commafeed.frontend.utils.ModelFactory.MF;
import com.google.common.collect.Iterables;
@Stateless
@SuppressWarnings("serial")
public class UserService extends GenericDAO<User, Long> {
@Inject

View File

@@ -10,6 +10,7 @@ import com.uaihebert.factory.EasyCriteriaFactory;
import com.uaihebert.model.EasyCriteria;
@Stateless
@SuppressWarnings("serial")
public class UserSettingsService extends GenericDAO<UserSettings, Long> {
public UserSettings findByUser(User user) {

View File

@@ -48,7 +48,7 @@ public class FeedFetcher {
String content = EntityUtils.toString(entity, "UTF-8");
feed = parser.parse(feedUrl, content);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
httpclient.getConnectionManager().shutdown();
}

View File

@@ -47,8 +47,9 @@ public class FeedParser {
feed.getEntries().add(entry);
}
} catch (Exception e) {
throw new FeedException("Could not parse feed : " + e.getMessage(),
e);
throw new FeedException(String.format(
"Could not parse feed from %s : %s", feedUrl,
e.getMessage()), e);
}
return feed;
}

View File

@@ -1,20 +1,26 @@
package com.commafeed.backend.feeds;
import java.util.List;
import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.Future;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.commafeed.backend.dao.FeedEntryService;
import com.commafeed.backend.dao.FeedService;
import com.commafeed.backend.model.Feed;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@Singleton
public class FeedTimer {
private static Logger log = LoggerFactory.getLogger(FeedTimer.class);
@Inject
FeedService feedService;
@@ -26,21 +32,32 @@ public class FeedTimer {
@Schedule(hour = "*", minute = "*", persistent = false)
private void timeout() {
List<Feed> feeds = feedService.findAll();
List<Future<Feed>> futures = Lists.newArrayList();
for (Feed feed : feeds) {
Future<Feed> future = fetcher.fetch(feed.getUrl());
futures.add(future);
Map<String, Feed> feeds = Maps.newHashMap();
for (Feed feed : feedService.findAll()) {
feeds.put(feed.getUrl(), feed);
}
for (Future<Feed> future : futures) {
Map<String, Future<Feed>> futures = Maps.newHashMap();
for (Feed feed : feeds.values()) {
Future<Feed> future = fetcher.fetch(feed.getUrl());
futures.put(feed.getUrl(), future);
}
for (String key : futures.keySet()) {
Future<Feed> future = futures.get(key);
try {
Feed feed = future.get();
feedEntryService
.updateEntries(feed.getUrl(), feed.getEntries());
} catch (Exception e) {
e.printStackTrace();
log.info(
"Unable to refresh feed " + key + " : "
+ e.getMessage(), e);
Feed feed = feeds.get(key);
feed.setLastUpdated(Calendar.getInstance().getTime());
feed.setMessage("Unable to refresh feed: " + e.getMessage());
feedService.update(feed);
}
}
}

View File

@@ -0,0 +1,85 @@
package com.commafeed.backend.feeds;
import java.io.StringReader;
import java.util.List;
import javax.ejb.Singleton;
import javax.inject.Inject;
import org.apache.commons.lang.StringUtils;
import com.commafeed.backend.dao.FeedCategoryService;
import com.commafeed.backend.dao.FeedService;
import com.commafeed.backend.dao.FeedSubscriptionService;
import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedCategory;
import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.model.User;
import com.sun.syndication.feed.opml.Opml;
import com.sun.syndication.feed.opml.Outline;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.WireFeedInput;
@Singleton
public class OPMLImporter {
@Inject
FeedService feedService;
@Inject
FeedSubscriptionService feedSubscriptionService;
@Inject
FeedCategoryService feedCategoryService;
@SuppressWarnings("unchecked")
public void importOpml(User user, String xml) throws FeedException {
WireFeedInput input = new WireFeedInput();
Opml feed = (Opml) input.build(new StringReader(xml));
List<Outline> outlines = (List<Outline>) feed.getOutlines();
for (Outline outline : outlines) {
handleOutline(user, outline, null);
}
}
@SuppressWarnings("unchecked")
private void handleOutline(User user, Outline outline, FeedCategory parent) {
if (StringUtils.isEmpty(outline.getType())) {
FeedCategory category = feedCategoryService.findByName(user,
outline.getText(), parent);
if (category == null) {
category = new FeedCategory();
category.setName(outline.getText());
category.setParent(parent);
category.setUser(user);
feedCategoryService.save(category);
}
List<Outline> children = outline.getChildren();
for (Outline child : children) {
handleOutline(user, child, category);
}
} else {
Feed feed = feedService.findByUrl(outline.getXmlUrl());
if (feed == null) {
feed = new Feed();
feed.setUrl(outline.getXmlUrl());
feedService.save(feed);
}
FeedSubscription sub = feedSubscriptionService.findByFeed(user,
feed);
if (sub == null) {
sub = new FeedSubscription();
sub.setFeed(feed);
sub.setUser(user);
feedSubscriptionService.save(sub);
}
sub.setCategory(parent);
sub.setTitle(outline.getText());
feedSubscriptionService.update(sub);
}
}
}

View File

@@ -24,6 +24,9 @@ public class Feed extends AbstractModel {
@Temporal(TemporalType.TIMESTAMP)
private Date lastUpdated;
@Column(length = 1024)
private String message;
@OneToMany(mappedBy = "feed", fetch = FetchType.EAGER)
private Set<FeedEntry> entries = Sets.newHashSet();
@@ -59,4 +62,12 @@ public class Feed extends AbstractModel {
this.entries = entries;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@@ -21,7 +21,7 @@ public class FeedEntry extends AbstractModel {
@ManyToOne
private Feed feed;
@Column(length = 256)
@Column(length = 2048)
private String title;
@Lob