package info.persistent.pushbot.data;
import com.google.appengine.api.datastore.Link;
import com.google.appengine.api.xmpp.JID;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import info.persistent.pushbot.util.Persistence;
import info.persistent.pushbot.util.Xmpp;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
@PersistenceCapable(
identityType = IdentityType.APPLICATION, detachable = "true")
public class Subscription {
private static final int MAX_SEEN_ENTRY_SIZE = 1000;
private static final Logger logger =
Logger.getLogger(Subscription.class.getName());
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
@Persistent
private String user;
@Persistent(defaultFetchGroup = "true")
private Link feedUrl;
@Persistent(defaultFetchGroup = "true")
@Extension(vendorName = "datanucleus", key = "gae.unindexed", value="true")
private Link hubUrl;
@Persistent
@Extension(vendorName = "datanucleus", key = "gae.unindexed", value="true")
private String title;
@Persistent(defaultFetchGroup = "true")
@Extension(vendorName = "datanucleus", key = "gae.unindexed", value="true")
private Set<String> seenEntryIds;
public Subscription(JID user, URL feedUrl, URL hubUrl, String title) {
this.user = Xmpp.toShortJid(user).getId();
this.feedUrl = new Link(feedUrl.toString());
this.hubUrl = new Link (hubUrl.toString());
this.title = title;
this.seenEntryIds = Sets.newHashSet();
}
public Long getId() {
return id;
}
public JID getUser() {
return new JID(user);
}
public URL getFeedUrl() {
try {
return new URL(feedUrl.getValue());
} catch (MalformedURLException err) {
// All stored URLs should be valid, since we're creating them from URL
// instances
throw new RuntimeException(err);
}
}
public URL getHubUrl() {
try {
return new URL(hubUrl.getValue());
} catch (MalformedURLException err) {
// Ditto
throw new RuntimeException(err);
}
}
public String getTitle() {
return title;
}
public ImmutableSet<String> getSeenEntryIds() {
return seenEntryIds != null
? ImmutableSet.<String>copyOf(seenEntryIds)
: ImmutableSet.<String>of();
}
public void addSeenEntryIds(Collection<String> entryIds) {
if (seenEntryIds == null) {
seenEntryIds = Sets.newHashSet();
}
int maxSeenEntrySize = MAX_SEEN_ENTRY_SIZE - entryIds.size();
if (seenEntryIds.size() >= maxSeenEntrySize) {
logger.warning("Subscription " + feedUrl.getValue() + " for " + user +
" had " + seenEntryIds.size() + " entries, dropping " +
(seenEntryIds.size() - maxSeenEntrySize));
// Ideally we'd drop the oldest entries, but we don't store timestamps...
seenEntryIds = Sets.newHashSet(
Lists.newArrayList(seenEntryIds).subList(0, maxSeenEntrySize));
}
seenEntryIds.addAll(entryIds);
}
public static List<Subscription> getSubscriptionsForUser(JID user) {
final String queryUserId = Xmpp.toShortJid(user).getId();
final List<Subscription> result = Lists.newArrayList();
Persistence.withManager(new Persistence.Closure() {
@SuppressWarnings("unchecked")
@Override public void run(PersistenceManager manager) {
Query query = manager.newQuery(Subscription.class);
query.setFilter("user == userParam");
query.declareParameters("String userParam");
result.addAll((List<Subscription>) query.execute(queryUserId));
query.closeAll();
}
});
return result;
}
public static List<Subscription> getSubscriptionsForUserAndFeedUrl(
JID user, URL feedUrl) {
final String queryUserId = Xmpp.toShortJid(user).getId();
final Link queryFeedUrl = new Link(feedUrl.toString());
final List<Subscription> result = Lists.newArrayList();
Persistence.withManager(new Persistence.Closure() {
@SuppressWarnings("unchecked")
@Override public void run(PersistenceManager manager) {
Query query = manager.newQuery(Subscription.class);
query.setFilter("user == userParam && feedUrl == feedUrlParam");
query.declareParameters("String userParam, " +
"com.google.appengine.api.datastore.Link feedUrlParam");
result.addAll(
(List<Subscription>) query.execute(queryUserId, queryFeedUrl));
query.closeAll();
}
});
return result;
}
}