package org.atlasapi.persistence.content.mongo;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.atlasapi.equiv.ContentRef;
import org.atlasapi.media.entity.Alias;
import org.atlasapi.media.entity.Container;
import org.atlasapi.media.entity.Content;
import org.atlasapi.media.entity.Described;
import org.atlasapi.media.entity.Identified;
import org.atlasapi.media.entity.Item;
import org.atlasapi.media.entity.LookupRef;
import org.atlasapi.media.entity.Publisher;
import org.atlasapi.persistence.content.ContentCategory;
import org.atlasapi.persistence.content.ContentPurger;
import org.atlasapi.persistence.content.ContentResolver;
import org.atlasapi.persistence.content.ContentWriter;
import org.atlasapi.persistence.content.listing.ContentLister;
import org.atlasapi.persistence.content.listing.ContentListingCriteria;
import org.atlasapi.persistence.lookup.LookupWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.metabroadcast.common.base.Maybe;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
public class MongoContentPurger implements ContentPurger {
private static final Logger log = LoggerFactory.getLogger(MongoContentPurger.class);
static final String ATLAS_EQUIVALENCE_ALIAS = "atlas:equivalence";
private final ContentLister contentLister;
private final ContentResolver contentResolver;
private final ContentWriter contentWriter;
private final MongoContentTables contentTables;
private final DBCollection lookupCollection;
private final LookupWriter explicitTransitiveLookupWriter;
private final LookupWriter generatedTransitiveLookupWriter;
public MongoContentPurger(ContentLister contentLister, ContentResolver contentResolver,
ContentWriter contentWriter, MongoContentTables contentTables,
DBCollection lookupCollection, LookupWriter explicitTransitiveLookupWriter,
LookupWriter generatedTransitiveLookupWriter) {
this.lookupCollection = checkNotNull(lookupCollection);
this.contentTables = checkNotNull(contentTables);
this.contentLister = checkNotNull(contentLister);
this.contentResolver = checkNotNull(contentResolver);
this.contentWriter = checkNotNull(contentWriter);
this.explicitTransitiveLookupWriter = checkNotNull(explicitTransitiveLookupWriter);
this.generatedTransitiveLookupWriter = checkNotNull(generatedTransitiveLookupWriter);
}
@Override
public void purge(Publisher publisher, Set<Publisher> equivalencesToRetainAsAliases) {
Iterator<Content> contentIterator =
contentLister.listContent(
new ContentListingCriteria.Builder()
.forPublisher(publisher)
.build()
);
while (contentIterator.hasNext()) {
Content c = contentIterator.next();
retainEquivalencesAsAliases(c, equivalencesToRetainAsAliases);
removeAllEquivalences(c);
deleteContent(c);
}
}
private void deleteContent(Content c) {
DBCollection contentCollection = contentTables.collectionFor(ContentCategory.categoryFor(c));
DBObject criteria = BasicDBObjectBuilder.start("_id", c.getCanonicalUri()).get();
contentCollection.remove(criteria);
lookupCollection.remove(criteria);
}
private void removeAllEquivalences(Content c) {
explicitTransitiveLookupWriter.writeLookup(ContentRef.valueOf(c), ImmutableSet.<ContentRef>of(), Publisher.all());
generatedTransitiveLookupWriter.writeLookup(ContentRef.valueOf(c), ImmutableSet.<ContentRef>of(), Publisher.all());
}
private void retainEquivalencesAsAliases(Content c,
Set<Publisher> equivalencesToRetainAsAliases) {
for (LookupRef lookupRef : c.getEquivalentTo()) {
if (equivalencesToRetainAsAliases.contains(lookupRef.publisher())) {
Identified equiv = contentResolver.findByCanonicalUris(ImmutableSet.of(lookupRef.uri()))
.getFirstValue()
.requireValue();
equiv.addAlias(new Alias(ATLAS_EQUIVALENCE_ALIAS, c.getCanonicalUri()));
write(equiv);
}
}
}
private void write(Identified identified) {
if (identified instanceof Item) {
contentWriter.createOrUpdate((Item) identified);
} else if (identified instanceof Container) {
contentWriter.createOrUpdate((Container) identified);
} else {
throw new IllegalArgumentException("Can't write " + identified.getCanonicalUri());
}
}
@Override
public void restoreEquivalences(Publisher publisher) {
Iterator<Content> contentIterator = contentLister.listContent(
new ContentListingCriteria.Builder()
.forPublisher(publisher)
.build()
);
while (contentIterator.hasNext()) {
Content content = contentIterator.next();
for (Alias alias : Iterables.filter(content.getAliases(), IS_EQUIVALENCE_ALIAS)) {
Maybe<Identified> contentFromPurgedPublisher =
contentResolver.findByCanonicalUris(ImmutableSet.of(alias.getValue())).getFirstValue();
if (contentFromPurgedPublisher.hasValue()) {
content.addEquivalentTo((Described) contentFromPurgedPublisher.requireValue());
HashSet<Alias> aliases = Sets.newHashSet(content.getAliases());
aliases.remove(alias);
content.setAliases(aliases);
write(content);
} else {
log.warn("Could not find equivalent content of {} for {} so not writing equivalence",
alias.getValue(), content.getCanonicalUri());
}
}
}
}
private final Predicate<Alias> IS_EQUIVALENCE_ALIAS = new Predicate<Alias>() {
@Override
public boolean apply(Alias alias) {
return ATLAS_EQUIVALENCE_ALIAS.equals(alias.getNamespace());
}
};
}