diff --git a/src/main/java/org/dstadler/audio/fm4/FM4.java b/src/main/java/org/dstadler/audio/fm4/FM4.java index 53995c7..b28ea9c 100644 --- a/src/main/java/org/dstadler/audio/fm4/FM4.java +++ b/src/main/java/org/dstadler/audio/fm4/FM4.java @@ -2,6 +2,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang3.time.DateUtils; +import org.apache.commons.lang3.time.FastDateFormat; import org.dstadler.commons.http.HttpClientWrapper; import org.dstadler.commons.logging.jdk.LoggerFactory; @@ -37,8 +39,21 @@ public class FM4 { * @return A list of {@link FM4Stream} * @throws IOException If fetching data via the FM4 REST API fails */ - public List fetchStreams() throws IOException { - return fetchStreams(FM4_API_URL, FM4_STREAM_URL_BASE); + public List fetchStreams(int days) throws IOException { + // 7 days minimum + if (days < 7) { + days = 7; + } + + List streams = new ArrayList<>(); + for (int day = days; day > 7; day--) { + String date = FastDateFormat.getInstance("yyyyMMdd").format(DateUtils.addDays(new Date(), (-1)*day)); + streams.addAll(fetchStreams(date)); + } + + streams.addAll(fetchStreams(FM4_API_URL, FM4_STREAM_URL_BASE)); + + return streams; } /** @@ -103,7 +118,7 @@ private static JsonNode parsAPI(String apiUrl) throws IOException { * @throws IOException If fetching data via the FM4 REST API fails */ public List filterStreams(String programKey) throws IOException { - List streams = fetchStreams(); + List streams = fetchStreams(14); return streams.stream(). // filter out future shows diff --git a/src/main/java/org/dstadler/audio/fm4/FM4Cache.java b/src/main/java/org/dstadler/audio/fm4/FM4Cache.java index 3497b10..36ff108 100644 --- a/src/main/java/org/dstadler/audio/fm4/FM4Cache.java +++ b/src/main/java/org/dstadler/audio/fm4/FM4Cache.java @@ -54,6 +54,7 @@ public class FM4Cache implements AutoCloseable { .build()); private final FM4 fm4; + private final int days; /** * Construct up the cache and start periodic background @@ -61,9 +62,12 @@ public class FM4Cache implements AutoCloseable { * * @param fm4 An instance of the FM4 access helper. * This is passed in to facilitate testing. + * @param days The number of days to cache. Should be between + * 7 and 30 for FM4 */ - public FM4Cache(FM4 fm4) { + public FM4Cache(FM4 fm4, int days) { this.fm4 = fm4; + this.days = days; executor.scheduleAtFixedRate(this::refresh, 0, 5, TimeUnit.MINUTES); } @@ -242,7 +246,7 @@ public void refresh() { try { // first get all streams by programKey Multimap streams = ArrayListMultimap.create(); - for (FM4Stream stream : fm4.fetchStreams()) { + for (FM4Stream stream : fm4.fetchStreams(days)) { streams.put(stream.getProgramKey(), stream); } diff --git a/src/test/java/org/dstadler/audio/fm4/FM4CacheTest.java b/src/test/java/org/dstadler/audio/fm4/FM4CacheTest.java index fdd8843..03b5728 100644 --- a/src/test/java/org/dstadler/audio/fm4/FM4CacheTest.java +++ b/src/test/java/org/dstadler/audio/fm4/FM4CacheTest.java @@ -40,7 +40,7 @@ public void tearDown() throws InterruptedException { @Test public void testCache() { - try (FM4Cache cache = new FM4Cache(new FM4())) { + try (FM4Cache cache = new FM4Cache(new FM4(), 7)) { assertEquals(0, cache.size()); cache.refresh(); @@ -59,7 +59,7 @@ public void testCache() { } // cache itself is not static, so size should be zero again now - try (FM4Cache cache = new FM4Cache(new FM4())) { + try (FM4Cache cache = new FM4Cache(new FM4(), 7)) { assertEquals(0, cache.size()); verifier.addObject(cache); @@ -70,12 +70,12 @@ public void testCache() { public void testGetNextNotFound() { try (FM4Cache cache = new FM4Cache(new FM4() { @Override - public List fetchStreams() throws IOException { + public List fetchStreams(int days) throws IOException { // only load two shows to make testing quick - List fm4Streams = super.fetchStreams(); + List fm4Streams = super.fetchStreams(days); return fm4Streams.subList(0, Math.min(2, fm4Streams.size())); } - })) { + }, 7)) { cache.refresh(); assertNull(cache.getNext(null)); @@ -99,12 +99,12 @@ public List fetchStreams() throws IOException { public void testGetNextFound() { try (FM4Cache cache = new FM4Cache(new FM4() { @Override - public List fetchStreams() throws IOException { + public List fetchStreams(int days) throws IOException { // only load two shows to make testing quick - List fm4Streams = super.fetchStreams(); + List fm4Streams = super.fetchStreams(days); return fm4Streams.subList(0, Math.min(2, fm4Streams.size())); } - })) { + }, 7)) { cache.refresh(); Collection fm4Streams = cache.allStreams(); @@ -142,12 +142,12 @@ public List fetchStreams() throws IOException { public void testGetPreviousNotFound() { try (FM4Cache cache = new FM4Cache(new FM4() { @Override - public List fetchStreams() throws IOException { + public List fetchStreams(int days) throws IOException { // only load two shows to make testing quick - List fm4Streams = super.fetchStreams(); + List fm4Streams = super.fetchStreams(days); return fm4Streams.subList(0, Math.min(2, fm4Streams.size())); } - })) { + }, 7)) { cache.refresh(); assertNull(cache.getNext(null)); @@ -171,12 +171,12 @@ public List fetchStreams() throws IOException { public void testGetPreviousFound() { try (FM4Cache cache = new FM4Cache(new FM4() { @Override - public List fetchStreams() throws IOException { + public List fetchStreams(int days) throws IOException { // only load two shows to make testing quick - List fm4Streams = super.fetchStreams(); + List fm4Streams = super.fetchStreams(days); return fm4Streams.subList(0, Math.min(2, fm4Streams.size())); } - })) { + }, 7)) { cache.refresh(); Collection fm4Streams = cache.allStreams(); @@ -214,12 +214,12 @@ public List fetchStreams() throws IOException { public void testGetNextByStreamURLNotFound() throws IOException { try (FM4Cache cache = new FM4Cache(new FM4() { @Override - public List fetchStreams() throws IOException { + public List fetchStreams(int days) throws IOException { // only load two shows to make testing quick - List fm4Streams = super.fetchStreams(); + List fm4Streams = super.fetchStreams(days); return fm4Streams.subList(0, Math.min(2, fm4Streams.size())); } - })) { + }, 7)) { cache.refresh(); assertNull(cache.getNextByStreamURL(null)); @@ -234,12 +234,12 @@ public List fetchStreams() throws IOException { public void testGetNextByStreamURLFound() throws IOException { try (FM4Cache cache = new FM4Cache(new FM4() { @Override - public List fetchStreams() throws IOException { + public List fetchStreams(int days) throws IOException { // only load two shows to make testing quick - List fm4Streams = super.fetchStreams(); + List fm4Streams = super.fetchStreams(days); return fm4Streams.subList(0, Math.min(2, fm4Streams.size())); } - })) { + }, 7)) { cache.refresh(); Collection fm4Streams = cache.allStreams(); @@ -279,10 +279,10 @@ public List fetchStreams() throws IOException { public void testIOException() { try (FM4Cache cache = new FM4Cache(new FM4() { @Override - public List fetchStreams() throws IOException { + public List fetchStreams(int days) throws IOException { throw new IOException("Test-exception"); } - })) { + }, 7)) { verifier.addObject(cache); cache.refresh(); @@ -291,7 +291,7 @@ public List fetchStreams() throws IOException { @Test public void testThread() throws InterruptedException { - try (FM4Cache cache = new FM4Cache(new FM4())) { + try (FM4Cache cache = new FM4Cache(new FM4(), 7)) { // wait for the thread be started for (int i = 0; i < 10; i++) { if (ExecutorUtil.lookupThread("FM4Cache") != null) { diff --git a/src/test/java/org/dstadler/audio/fm4/FM4StreamTest.java b/src/test/java/org/dstadler/audio/fm4/FM4StreamTest.java index dcf18f1..4d78839 100644 --- a/src/test/java/org/dstadler/audio/fm4/FM4StreamTest.java +++ b/src/test/java/org/dstadler/audio/fm4/FM4StreamTest.java @@ -35,7 +35,7 @@ public class FM4StreamTest { @Test public void testFM4Stream() throws IOException, ParseException { - List fm4Streams = fm4.fetchStreams(); + List fm4Streams = fm4.fetchStreams(7); FM4Stream fm4Stream = fm4Streams.get(0); assertNotNull(fm4Stream.getTitle()); @@ -83,7 +83,7 @@ public void testFM4Stream() throws IOException, ParseException { @Test public void testStreams() throws IOException { FM4 fm4 = new FM4(); - List fm4Streams = fm4.fetchStreams(); + List fm4Streams = fm4.fetchStreams(7); Assume.assumeFalse("Should get some streams", fm4Streams.isEmpty()); @@ -94,6 +94,15 @@ public void testStreams() throws IOException { assertNotNull(streams.get(0)); } + @Test + public void testStreamsMoreDays() throws IOException { + FM4 fm4 = new FM4(); + List fm4Streams7 = fm4.fetchStreams(7); + List fm4Streams14 = fm4.fetchStreams(14); + + assertTrue(fm4Streams14.size() > fm4Streams7.size()); + } + @Test public void testEquals() { ObjectNode node = objectMapper.createObjectNode(); diff --git a/src/test/java/org/dstadler/audio/fm4/FM4Test.java b/src/test/java/org/dstadler/audio/fm4/FM4Test.java index 094ef97..7c84e1a 100644 --- a/src/test/java/org/dstadler/audio/fm4/FM4Test.java +++ b/src/test/java/org/dstadler/audio/fm4/FM4Test.java @@ -28,7 +28,9 @@ import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.logging.Logger; import static org.dstadler.audio.fm4.FM4Stream.FM4_STREAM_URL_BASE; @@ -36,6 +38,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; public class FM4Test { @@ -47,7 +50,7 @@ public class FM4Test { @Test public void testFetch() throws IOException, ParseException { - List fm4Streams = fm4.fetchStreams(); + List fm4Streams = fm4.fetchStreams(7); assertNotNull(fm4Streams); assertFalse(fm4Streams.isEmpty()); @@ -63,6 +66,22 @@ public void testFetch() throws IOException, ParseException { } } + @Test + public void testFetchNoDuplicates() throws IOException { + List fm4Streams = fm4.fetchStreams(14); + Set seenStreams = new HashSet<>(); + for (FM4Stream stream : fm4Streams) { + assertTrue("Had duplicate for " + stream, + seenStreams.add(stream.getShortTime())); + } + } + + @Test + public void testFetchTooManyDays() { + assertThrows(IOException.class, + () -> fm4.fetchStreams(90)); + } + @Test public void testFetchForDate() throws IOException, ParseException { String date = FastDateFormat.getInstance("yyyyMMdd").format(DateUtils.addDays(new Date(), -3)); @@ -85,7 +104,7 @@ public void testFetchForDate() throws IOException, ParseException { @Ignore("Fetches streams for all programs, this runs for some time, so disable for CI") @Test public void testFetchAllStreams() throws IOException { - List fm4Streams = fm4.fetchStreams(); + List fm4Streams = fm4.fetchStreams(14); assertNotNull(fm4Streams); assertFalse(fm4Streams.isEmpty());