package org.atlasapi.persistence.content;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import com.metabroadcast.applications.client.model.internal.Application;
import com.metabroadcast.applications.client.model.internal.ApplicationConfiguration;
import org.atlasapi.application.v3.DefaultApplication;
import org.atlasapi.media.entity.Content;
import org.atlasapi.media.entity.Episode;
import org.atlasapi.media.entity.Identified;
import org.atlasapi.media.entity.LookupRef;
import org.atlasapi.media.entity.Publisher;
import org.atlasapi.output.Annotation;
import org.atlasapi.persistence.lookup.InMemoryLookupEntryStore;
import org.atlasapi.persistence.lookup.entry.LookupEntry;
import org.atlasapi.persistence.lookup.entry.LookupEntryStore;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
public class DefaultEquivalentContentResolverTest {
private DummyKnownTypeContentResolver contentResolver;
private LookupEntryStore lookupResolver;
private EquivalentContentResolver equivResolver;
private Application application = mock(Application.class);
@Before
public void setUp() {
contentResolver = new DummyKnownTypeContentResolver();
lookupResolver = new InMemoryLookupEntryStore();
equivResolver = new DefaultEquivalentContentResolver(contentResolver, lookupResolver);
}
@Test
public void testResolvesSimpleContent() {
Episode subject = episode("testUri", 1, Publisher.BBC);
Episode equiv = episode("equiv", 2, Publisher.PA);
Iterable<String> uris = ImmutableSet.of(subject.getCanonicalUri());
Set<Annotation> annotations = Annotation.defaultAnnotations();
when(application.getConfiguration()).thenReturn(configWithSources(Publisher.PA, Publisher.BBC));
lookupResolver.store(entry(subject, ImmutableSet.of(equiv), equiv));
contentResolver.respondTo(ImmutableSet.of(subject, equiv));
EquivalentContent content = equivResolver.resolveUris(uris, application, annotations, false);
assertEquals(1, content.asMap().size());
assertNull(content.asMap().get(equiv.getCanonicalUri()));
checkEquivContent(content, subject, equiv);
}
@Test
public void testResolvesContentWithTwoKeys() {
Episode subject1 = episode("testUri1", 1, Publisher.BBC);
Episode subject2 = episode("testUri2", 2, Publisher.BBC);
Episode equiv = episode("equiv", 3, Publisher.PA);
Iterable<String> uris = ImmutableSet.of(subject1.getCanonicalUri(), subject2.getCanonicalUri());
Set<Annotation> annotations = Annotation.defaultAnnotations();
when(application.getConfiguration()).thenReturn(configWithSources(Publisher.PA, Publisher.BBC));
lookupResolver.store(entry(subject1, ImmutableSet.of(equiv), equiv));
lookupResolver.store(entry(subject2, ImmutableSet.<Content>of()));
contentResolver.respondTo(ImmutableSet.of(subject1, subject2, equiv));
EquivalentContent content = equivResolver.resolveUris(uris, application, annotations, false);
assertEquals(2, content.asMap().size());
assertNull(content.asMap().get(equiv.getCanonicalUri()));
checkEquivContent(content, subject1, equiv);
checkEquivContent(content, subject2);
}
@Test
public void testReturnsOnlyRequestedContentFromPrecedentSourceAndRemovesAdjacentsOfThoseRemoved() {
Episode subject = episode("subject", 4, Publisher.PA);
Episode equiv = episode("equiv", 2, Publisher.BBC);
Episode filtered = episode("filtered", 1, Publisher.PA);
Episode filteredEquiv = episode("filteredEquiv", 3, Publisher.C4);
Episode invisible = episode("invisible", 5, Publisher.FIVE);
Iterable<String> uris = ImmutableSet.of(subject.getCanonicalUri());
Set<Annotation> annotations = Annotation.defaultAnnotations();
when(application.getConfiguration()).thenReturn(configWithSources(Publisher.PA, Publisher.BBC, Publisher.C4));
lookupResolver.store(entry(subject, ImmutableSet.of(equiv, invisible),
equiv, filtered, filteredEquiv, invisible));
lookupResolver.store(entry(filtered, ImmutableSet.of(filteredEquiv),
subject, equiv, filteredEquiv));
contentResolver.respondTo(ImmutableSet.of(subject, equiv, filtered, filteredEquiv));
EquivalentContent content = equivResolver.resolveUris(uris, application, annotations, false);
assertEquals(1, content.asMap().size());
assertNull(content.asMap().get(equiv.getCanonicalUri()));
checkEquivContent(content, subject, equiv);
assertEquals(ImmutableSet.copyOf(subject.getEquivalentTo()),
ImmutableSet.copyOf(Iterables.transform(ImmutableList.of(subject, equiv, invisible), LookupRef.FROM_DESCRIBED))
);
}
@Test
public void testCanLookupTwoThingsWhereEachIsRemovedFromTheOther() {
Episode subject = episode("subject", 4, Publisher.PA);
Episode equiv = episode("equiv", 2, Publisher.BBC);
Episode filtered = episode("filtered", 1, Publisher.PA);
Episode filteredEquiv = episode("filteredEquiv", 3, Publisher.C4);
Iterable<String> uris = ImmutableSet.of(subject.getCanonicalUri(),
filtered.getCanonicalUri());
Set<Annotation> annotations = Annotation.defaultAnnotations();
when(application.getConfiguration()).thenReturn(configWithSources(Publisher.PA, Publisher.BBC, Publisher.C4));
lookupResolver.store(entry(subject, ImmutableSet.of(equiv),
equiv, filtered, filteredEquiv));
lookupResolver.store(entry(filtered, ImmutableSet.of(filteredEquiv),
subject, equiv, filteredEquiv));
contentResolver.respondTo(ImmutableSet.of(subject, equiv, filtered, filteredEquiv));
EquivalentContent content = equivResolver.resolveUris(uris, application, annotations, false);
assertEquals(2, content.asMap().size());
assertNull(content.asMap().get(equiv.getCanonicalUri()));
assertNull(content.asMap().get(filteredEquiv.getCanonicalUri()));
checkEquivContent(content, subject, equiv);
checkEquivContent(content, filtered, filteredEquiv);
}
@Test
public void testOnlyResolvesLowestItemFromPrecedentSourceWhenNonPrecedentSourceItemRequested() {
Episode subject = episode("subject", 4, Publisher.PA);
Episode equiv = episode("equiv", 2, Publisher.BBC);
Episode filtered = episode("filtered", 1, Publisher.PA);
Episode filteredEquiv = episode("filteredEquiv", 3, Publisher.C4);
Iterable<String> uris = ImmutableSet.of(equiv.getCanonicalUri(),
filteredEquiv.getCanonicalUri());
Set<Annotation> annotations = Annotation.defaultAnnotations();
when(application.getConfiguration()).thenReturn(configWithSources(Publisher.PA, Publisher.BBC, Publisher.C4));
lookupResolver.store(entry(subject, ImmutableSet.of(equiv),
equiv, filtered, filteredEquiv));
lookupResolver.store(entry(equiv, ImmutableSet.of(subject),
subject, filtered, filteredEquiv));
lookupResolver.store(entry(filtered, ImmutableSet.of(filteredEquiv),
subject, equiv, filteredEquiv));
lookupResolver.store(entry(filteredEquiv, ImmutableSet.of(filtered),
subject, equiv, filtered));
contentResolver.respondTo(ImmutableSet.of(subject, equiv, filtered, filteredEquiv));
EquivalentContent content = equivResolver.resolveUris(uris, application, annotations, false);
assertEquals(2, content.asMap().size());
assertNull(content.asMap().get(subject.getCanonicalUri()));
assertNull(content.asMap().get(filtered.getCanonicalUri()));
checkEquivContent(content, equiv, filtered, filteredEquiv);
checkEquivContent(content, filteredEquiv, filtered);
}
@Test
public void testSubjectAlwaysKeepsItsAdjacents() {
Episode subject = episode("subject", 4, Publisher.PA);
Episode disabled = episode("disabled", 5, Publisher.FIVE);
Episode equiv = episode("equiv", 2, Publisher.BBC);
Episode filtered = episode("filtered", 1, Publisher.PA);
Iterable<String> uris = ImmutableSet.of(subject.getCanonicalUri());
Set<Annotation> annotations = Annotation.defaultAnnotations();
when(application.getConfiguration()).thenReturn(configWithSources(Publisher.PA, Publisher.BBC, Publisher.C4));
lookupResolver.store(entry(subject, ImmutableSet.of(equiv, disabled),
equiv, filtered, disabled));
lookupResolver.store(entry(filtered, ImmutableSet.of(equiv),
subject, equiv, disabled));
contentResolver.respondTo(ImmutableSet.of(subject, equiv, filtered,disabled));
EquivalentContent content = equivResolver.resolveUris(uris, application, annotations, false);
assertEquals(1, content.asMap().size());
assertNull(content.asMap().get(equiv.getCanonicalUri()));
checkEquivContent(content, subject, equiv);
}
private ApplicationConfiguration configWithSources(Publisher... srcs) {
return ApplicationConfiguration.builder()
.withPrecedence(Arrays.asList(srcs))
.withEnabledWriteSources(ImmutableList.of())
.build();
}
private <C extends Content> void checkEquivContent(EquivalentContent content, C subj, C...equivs) {
Collection<Content> equivContent = content.asMap().get(subj.getCanonicalUri());
assertNotNull(equivContent);
Map<String,Content> equivMap = Maps.uniqueIndex(equivContent, Identified.TO_URI);
assertEquals(equivs.length+1, equivMap.size());
assertEquals(subj, equivMap.get(subj.getCanonicalUri()));
for (C eq : equivs) {
assertEquals(eq, equivMap.get(eq.getCanonicalUri()));
}
}
private LookupEntry entry(Content c, Iterable<? extends Content> direct, Content... equivs) {
return LookupEntry.lookupEntryFrom(c)
.copyWithDirectEquivalents(Iterables.transform(direct, LookupRef.FROM_DESCRIBED))
.copyWithEquivalents(Collections2.transform(ImmutableSet.copyOf(equivs), LookupRef.FROM_DESCRIBED));
}
private Episode episode(String uri, long id, Publisher src) {
Episode ep = new Episode(uri, uri, src);
ep.setId(id);
return ep;
}
}