package org.atlasapi.media.channel;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.metabroadcast.common.persistence.mongo.MongoBuilders.where;
import static com.metabroadcast.common.persistence.mongo.MongoConstants.SINGLE;
import static com.metabroadcast.common.persistence.mongo.MongoConstants.UPSERT;
import java.util.Set;
import org.atlasapi.persistence.ids.MongoSequentialIdGenerator;
import org.atlasapi.persistence.media.entity.IdentifiedTranslator;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.metabroadcast.common.persistence.mongo.DatabasedMongo;
import com.metabroadcast.common.persistence.mongo.MongoConstants;
import com.metabroadcast.common.persistence.mongo.MongoQueryBuilder;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
public class MongoChannelGroupStore implements ChannelGroupStore {
private static final String CHANNEL_GROUP_CHANNEL_NUMBERING_ID_KEY =
ChannelGroupTranslator.CHANNEL_NUMBERINGS_KEY + "." +
ChannelNumberingTranslator.CHANNEL_KEY + "." + MongoConstants.ID;
private DBCollection channelGroups;
private static final String COLLECTION_NAME = "channelGroups";
private MongoSequentialIdGenerator idGenerator;
private ChannelGroupTranslator translator = new ChannelGroupTranslator();
public MongoChannelGroupStore(DatabasedMongo mongo) {
this.channelGroups = mongo.collection(COLLECTION_NAME);
this.idGenerator = new MongoSequentialIdGenerator(mongo, COLLECTION_NAME);
}
@Override
public Optional<ChannelGroup> channelGroupFor(Long id) {
return Optional.fromNullable(translator.fromDBObject(channelGroups.findOne(id), null));
}
@Override
public Optional<ChannelGroup> channelGroupFor(String canonicalUri) {
return Optional.fromNullable(translator.fromDBObject(
channelGroups.findOne(where().fieldEquals(IdentifiedTranslator.CANONICAL_URL, canonicalUri).build()), null));
}
@Override
public Iterable<ChannelGroup> channelGroupsFor(Iterable<? extends Long> ids) {
return transform(channelGroups.find(new BasicDBObject(MongoConstants.ID, new BasicDBObject(MongoConstants.IN,ids))));
}
public Iterable<ChannelGroup> transform(DBCursor dbos) {
return Iterables.transform(dbos, new Function<DBObject, ChannelGroup>() {
@Override
public ChannelGroup apply(DBObject input) {
return translator.fromDBObject(input, null);
}
});
}
@Override
public Iterable<ChannelGroup> channelGroups() {
return transform(channelGroups.find());
}
@Override
public ChannelGroup createOrUpdate(ChannelGroup group) {
checkNotNull(group);
if (group.getId() == null) {
group.setId(idGenerator.generateRaw());
} else {
Optional<ChannelGroup> resolved = channelGroupFor(group.getId());
Preconditions.checkState(resolved.isPresent(), "Channel Group not found to update");
removeOldReferences(group, resolved.get());
}
if (group instanceof Region) {
Region region = (Region) group;
if (region.getPlatform() != null) {
Optional<ChannelGroup> possiblePlatform = channelGroupFor(region.getPlatform());
Preconditions.checkState(possiblePlatform.isPresent(), "Could not resolve platform with id " + region.getPlatform());
Platform platform = (Platform) possiblePlatform.get();
platform.addRegion(region);
channelGroups.update(new BasicDBObject(MongoConstants.ID, platform.getId()), translator.toDBObject(null, platform), UPSERT, SINGLE);
}
}
channelGroups.update(new BasicDBObject(MongoConstants.ID, group.getId()), translator.toDBObject(null, group), UPSERT, SINGLE);
return group;
}
@Override
public void deleteChannelGroupById(long channelGroupId) {
checkNotNull(channelGroupId);
channelGroups.remove(new BasicDBObject(MongoConstants.ID, channelGroupId));
}
private void removeOldReferences(ChannelGroup newGroup, ChannelGroup existingGroup) {
if (newGroup instanceof Region) {
Region existingRegion = (Region)existingGroup;
Region newRegion = (Region)newGroup;
if (existingRegion.getPlatform() != null) {
if (newRegion.getPlatform() == null || !existingRegion.getPlatform().equals(newRegion.getPlatform())) {
Optional<ChannelGroup> maybeOldPlatform = channelGroupFor(existingRegion.getPlatform());
Preconditions.checkState(maybeOldPlatform.isPresent(), String.format("Platform with id %s not found for region with id %s", existingRegion.getPlatform(), existingRegion.getId()));
Platform oldPlatform = (Platform)maybeOldPlatform.get();
Set<Long> regions = Sets.newHashSet(oldPlatform.getRegions());
regions.remove(existingRegion.getId());
oldPlatform.setRegionIds(regions);
channelGroups.update(new BasicDBObject(MongoConstants.ID, oldPlatform.getId()), translator.toDBObject(null, oldPlatform), UPSERT, SINGLE);
}
}
}
}
@Override
public Iterable<ChannelGroup> channelGroupsFor(Channel channel) {
return transform(channelGroups.find(where().fieldEquals(CHANNEL_GROUP_CHANNEL_NUMBERING_ID_KEY, channel.getId()).build()));
}
@Override
public Optional<ChannelGroup> fromAlias(String alias) {
MongoQueryBuilder query = new MongoQueryBuilder()
.fieldEquals("aliases", alias);
DBCursor cursor = channelGroups.find(query.build());
if (Iterables.isEmpty(cursor)) {
return Optional.absent();
}
return Optional.fromNullable(translator.fromDBObject(Iterables.getOnlyElement(cursor), null));
// for (DBObject dbo : channelGroups.find()) {
// ChannelGroup channelGroup = translator.fromDBObject(dbo, null);
// for (String channelGroupAlias : channelGroup.getAliasUrls()) {
// if (alias.equals(channelGroupAlias)) {
// return Optional.of(channelGroup);
// }
// }
// }
// return Optional.absent();
}
}