package org.atlasapi.media.channel;
import org.atlasapi.media.entity.Identified;
import org.atlasapi.media.entity.Image;
import org.atlasapi.media.entity.MediaType;
import org.atlasapi.media.entity.Publisher;
import org.atlasapi.media.entity.RelatedLink;
import org.atlasapi.persistence.ModelTranslator;
import org.atlasapi.persistence.media.entity.IdentifiedTranslator;
import org.atlasapi.persistence.media.entity.RelatedLinkTranslator;
import com.metabroadcast.common.persistence.translator.TranslatorUtils;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.base.Preconditions.checkNotNull;
public class ChannelTranslator implements ModelTranslator<Channel> {
public static final String TITLE = "title";
public static final String TITLES = "titles";
public static final String PUBLISHER = "publisher";
public static final String BROADCASTER = "broadcaster";
public static final String MEDIA_TYPE = "mediaType";
public static final String AVAILABLE_ON = "availableOn";
public static final String HIGH_DEFINITION = "highDefinition";
public static final String REGIONAL = "regional";
public static final String ADULT = "adult";
public static final String TIMESHIFT = "timeshift";
public static final String KEY = "key";
public static final String IMAGE = "image";
public static final String IMAGES = "images";
public static final String NEW_IMAGES = "new_images";
public static final String RELATED_LINKS = "relatedLinks";
public static final String PARENT = "parent";
public static final String VARIATIONS = "variations";
public static final String NUMBERINGS = "numberings";
public static final String START_DATE = "startDate";
public static final String END_DATE = "endDate";
public static final String GENRES_KEY = "genres";
public static final String ADVERTISE_FROM = "advertiseFrom";
public static final String SHORT_DESCRIPTION = "shortDescription";
public static final String MEDIUM_DESCRIPTION = "mediumDescription";
public static final String LONG_DESCRIPTION = "longDescription";
public static final String REGION = "region";
public static final String TARGET_REGIONS = "targetRegions";
public static final String CHANNEL_TYPE = "channelType";
public static final String URI = "uri";
public static final String INTERACTIVE = "interactive";
private ModelTranslator<Identified> identifiedTranslator;
private ChannelNumberingTranslator channelNumberingTranslator;
private TemporalTitleTranslator temporalTitleTranslator;
private final TemporalImageTranslator temporalImageTranslator;
private RelatedLinkTranslator relatedLinkTranslator;
public ChannelTranslator() {
this.identifiedTranslator = new IdentifiedTranslator(true);
this.channelNumberingTranslator = new ChannelNumberingTranslator();
this.temporalTitleTranslator = new TemporalTitleTranslator();
this.temporalImageTranslator = new TemporalImageTranslator();
this.relatedLinkTranslator = new RelatedLinkTranslator();
}
@Override
public DBObject toDBObject(DBObject dbObject, Channel model) {
checkNotNull(model.getMediaType());
dbObject = new BasicDBObject();
identifiedTranslator.toDBObject(dbObject, model);
temporalTitleTranslator.fromTemporalTitleSet(dbObject, TITLES, model.getAllTitles());
temporalImageTranslator.fromTemporalImageSet(dbObject, NEW_IMAGES, model.getAllImages());
// TODO remove this once migration is complete
setPreviousOldChannelImagesField(dbObject, IMAGES, model.getAllImages());
encodeRelatedLinks(dbObject, model);
TranslatorUtils.from(
dbObject,
MEDIA_TYPE,
model.getMediaType() != null ? model.getMediaType().name() : null
);
TranslatorUtils.from(dbObject, PUBLISHER, model.getSource().key());
TranslatorUtils.from(dbObject, HIGH_DEFINITION, model.getHighDefinition());
TranslatorUtils.from(dbObject, REGIONAL, model.getRegional());
TranslatorUtils.from(dbObject, ADULT, model.getAdult());
TranslatorUtils.fromDuration(dbObject, TIMESHIFT, model.getTimeshift());
TranslatorUtils.from(
dbObject,
BROADCASTER,
model.getBroadcaster() != null ? model.getBroadcaster().key() : null
);
if (model.getAvailableFrom() != null) {
TranslatorUtils.fromSet(
dbObject,
ImmutableSet.copyOf(transform(model.getAvailableFrom(), Publisher.TO_KEY)),
AVAILABLE_ON
);
}
TranslatorUtils.from(dbObject, KEY, model.getKey());
TranslatorUtils.from(dbObject, PARENT, model.getParent());
if (model.getVariations() != null) {
TranslatorUtils.fromLongSet(dbObject, VARIATIONS, model.getVariations());
}
if (model.getChannelNumbers() != null) {
channelNumberingTranslator.fromChannelNumberingSet(
dbObject,
NUMBERINGS,
model.getChannelNumbers()
);
}
TranslatorUtils.fromLocalDate(dbObject, START_DATE, model.getStartDate());
TranslatorUtils.fromLocalDate(dbObject, END_DATE, model.getEndDate());
TranslatorUtils.fromSet(dbObject, model.getGenres(), GENRES_KEY);
TranslatorUtils.fromDateTime(dbObject, ADVERTISE_FROM, model.getAdvertiseFrom());
TranslatorUtils.from(dbObject, SHORT_DESCRIPTION, model.getShortDescription());
TranslatorUtils.from(dbObject, MEDIUM_DESCRIPTION, model.getMediumDescription());
TranslatorUtils.from(dbObject, LONG_DESCRIPTION, model.getLongDescription());
TranslatorUtils.from(dbObject, REGION, model.getRegion());
TranslatorUtils.fromSet(dbObject, model.getTargetRegions(), TARGET_REGIONS);
ChannelType channelType = model.getChannelType();
if (channelType != null) {
TranslatorUtils.from(dbObject, CHANNEL_TYPE, channelType.name());
}
TranslatorUtils.from(dbObject, INTERACTIVE, model.getInteractive());
return dbObject;
}
@Override
public Channel fromDBObject(DBObject dbObject, Channel model) {
if (dbObject == null) {
return null;
}
if (model == null) {
model = Channel.builder().build();
}
model.setSource(Publisher.fromKey(
TranslatorUtils.toString(dbObject, PUBLISHER)
).requireValue());
model.setMediaType(MediaType.valueOf(TranslatorUtils.toString(dbObject, MEDIA_TYPE)));
if (dbObject.containsField(TITLES)) {
model.setTitles(temporalTitleTranslator.toTemporalTitleSet(dbObject, TITLES));
}
if (dbObject.containsField(TITLE)) {
model.addTitle(TranslatorUtils.toString(dbObject, TITLE));
}
if (dbObject.containsField(NEW_IMAGES)) {
model.setImages(temporalImageTranslator.toTemporalImageSet(dbObject, NEW_IMAGES));
}
decodeRelatedLinks(dbObject, model);
model.setKey((String) dbObject.get(KEY));
model.setHighDefinition(TranslatorUtils.toBoolean(dbObject, HIGH_DEFINITION));
model.setRegional(TranslatorUtils.toBoolean(dbObject, REGIONAL));
model.setAdult(TranslatorUtils.toBoolean(dbObject, ADULT));
model.setTimeshift(TranslatorUtils.toDuration(dbObject, TIMESHIFT));
model.setAvailableFrom(Iterables.transform(
TranslatorUtils.toSet(dbObject, AVAILABLE_ON),
Publisher.FROM_KEY
));
String broadcaster = TranslatorUtils.toString(dbObject, BROADCASTER);
model.setBroadcaster(broadcaster != null
? Publisher.fromKey(broadcaster).valueOrNull()
: null);
model.setParent(TranslatorUtils.toLong(dbObject, PARENT));
model.setVariationIds(TranslatorUtils.toLongSet(dbObject, VARIATIONS));
model.setChannelNumbers(channelNumberingTranslator.toChannelNumberingSet(
dbObject,
NUMBERINGS
));
model.setStartDate(TranslatorUtils.toLocalDate(dbObject, START_DATE));
model.setEndDate(TranslatorUtils.toLocalDate(dbObject, END_DATE));
model.setAdvertiseFrom(TranslatorUtils.toDateTime(dbObject, ADVERTISE_FROM));
if (dbObject.containsField(GENRES_KEY)) {
model.setGenres(TranslatorUtils.toSet(dbObject, GENRES_KEY));
}
model.setShortDescription(TranslatorUtils.toString(dbObject, SHORT_DESCRIPTION));
model.setMediumDescription(TranslatorUtils.toString(dbObject, MEDIUM_DESCRIPTION));
model.setLongDescription(TranslatorUtils.toString(dbObject, LONG_DESCRIPTION));
model.setRegion(TranslatorUtils.toString(dbObject, REGION));
model.setTargetRegions(TranslatorUtils.toSet(dbObject, TARGET_REGIONS));
String channelType = TranslatorUtils.toString(dbObject, CHANNEL_TYPE);
if (channelType != null) {
model.setChannelType(ChannelType.valueOf(channelType));
}
model.setInteractive(TranslatorUtils.toBoolean(dbObject, INTERACTIVE));
return (Channel) identifiedTranslator.fromDBObject(dbObject, model);
}
@SuppressWarnings("unchecked")
private void decodeRelatedLinks(DBObject dbObject, Channel channel) {
if (dbObject.containsField(RELATED_LINKS)) {
channel.setRelatedLinks(Iterables.transform(
(Iterable<DBObject>) dbObject.get(RELATED_LINKS),
input -> relatedLinkTranslator.fromDBObject(input)
));
}
}
private void encodeRelatedLinks(DBObject dbObject, Channel channel) {
if (!channel.getRelatedLinks().isEmpty()) {
BasicDBList values = new BasicDBList();
for (RelatedLink link : channel.getRelatedLinks()) {
values.add(relatedLinkTranslator.toDBObject(link));
}
dbObject.put(RELATED_LINKS, values);
}
}
// Translates the new images set into the previous set of images, for migration purposes
// uses the title translator, as they have the same form, and use the same keys
// to determine which are the images which were used previously, we use the IS_PRIMARY_IMAGE filter,
// which returns images of theme Light_Opaque
private void setPreviousOldChannelImagesField(DBObject dbObject, String key,
Iterable<TemporalField<Image>> newImages) {
Iterable<TemporalField<String>> primaryImages = Iterables.transform(
Iterables.filter(
newImages,
input -> {
Image image = input.getValue();
return Channel.IS_PRIMARY_IMAGE.apply(image);
}
),
input -> new TemporalField<>(
input.getValue().getCanonicalUri(),
input.getStartDate(),
input.getEndDate()
)
);
BasicDBList values = new BasicDBList();
for (TemporalField<String> value : primaryImages) {
if (value != null) {
values.add(temporalTitleTranslator.toDBObject(value));
}
}
dbObject.put(key, values);
}
}