Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Populate Radio Search Service #12

Merged
merged 2 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>dev.migwel.icyreader</groupId>
<artifactId>IcyReader</artifactId>
<version>1.0-RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand All @@ -36,6 +40,12 @@
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand All @@ -44,6 +54,16 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<excludes>
<exclude>**/*ManualTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/dev/migwel/sts/model/Song.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
package dev.migwel.sts.model;

public record Song(String artist, String title) {}
/**
* Representation of a song playing "somewhere"
*
* @param artist The artist performing that song
* @param title The title of the number
* @param rawData It can happen that parsing the artist and title can be tricky and what we have is
* raw data of what's playing. We may want this raw data either to save it and parse it manually
* later or for debugging reasons
*/
public record Song(String artist, String title, String rawData) {}
15 changes: 15 additions & 0 deletions src/main/java/dev/migwel/sts/radio/IcyReaderProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.migwel.sts.radio;

import dev.migwel.icyreader.IcyReader;
import org.springframework.stereotype.Component;

import javax.annotation.ParametersAreNonnullByDefault;

@Component
@ParametersAreNonnullByDefault
class IcyReaderProvider {

IcyReader getIcyReader(String url) {
return new IcyReader.IcyReaderBuilder(url).build();
}
}
30 changes: 27 additions & 3 deletions src/main/java/dev/migwel/sts/radio/RadioSearchService.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
package dev.migwel.sts.radio;

import dev.migwel.icyreader.IcyReader;
import dev.migwel.icyreader.SongInfo;
import dev.migwel.sts.model.RadioSearchRequest;
import dev.migwel.sts.model.Song;
import dev.migwel.sts.service.SearchService;
import org.springframework.stereotype.Component;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Component
import javax.annotation.CheckForNull;

@Service
public class RadioSearchService implements SearchService<RadioSearchRequest> {

private final IcyReaderProvider icyReaderProvider;

@Autowired
public RadioSearchService(IcyReaderProvider icyReaderProvider) {
this.icyReaderProvider = icyReaderProvider;
}

@Override
public boolean isRelevant(Class<?> searchRequestType) {
return searchRequestType.isAssignableFrom(RadioSearchRequest.class);
}

@Override
public Optional<Song> search(RadioSearchRequest searchRequest) {
return Optional.empty();
IcyReader reader = icyReaderProvider.getIcyReader(searchRequest.url());
return convert(reader.currentlyPlaying());
}

private Optional<Song> convert(@CheckForNull SongInfo songInfo) {
if (songInfo == null) {
return Optional.empty();
}
if (songInfo.artist() == null && songInfo.title() == null) {
return Optional.empty();
}
return Optional.of(new Song(songInfo.artist(), songInfo.title(), songInfo.rawData()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.migwel.sts.radio;

import static org.junit.jupiter.api.Assertions.*;

import dev.migwel.sts.model.RadioSearchRequest;
import dev.migwel.sts.model.Song;

import org.junit.jupiter.api.Test;

import java.util.Optional;

class RadioSearchServiceManualTest {

private final RadioSearchService radioSearchService =
new RadioSearchService(new IcyReaderProvider());

@Test
void search_NPORadio2() {
Optional<Song> optionalSong =
radioSearchService.search(
new RadioSearchRequest("https://icecast.omroep.nl/radio2-bb-mp3"));
assertTrue(optionalSong.isPresent());
System.out.println(optionalSong.get());
}
}
62 changes: 62 additions & 0 deletions src/test/java/dev/migwel/sts/radio/RadioSearchServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package dev.migwel.sts.radio;

import dev.migwel.icyreader.IcyReader;
import dev.migwel.icyreader.SongInfo;
import dev.migwel.sts.model.RadioSearchRequest;
import dev.migwel.sts.model.Song;
import dev.migwel.sts.model.SonosSearchRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

class RadioSearchServiceTest {

private final IcyReader icyReader = mock(IcyReader.class);
private final IcyReaderProvider icyReaderProvider = mock(IcyReaderProvider.class);
private final RadioSearchService radioSearchService = new RadioSearchService(icyReaderProvider);

@BeforeEach
void before() {
doReturn(icyReader).when(icyReaderProvider).getIcyReader(any());
}

@Test
void isRelevant_radioSearchRequest() {
assertTrue(radioSearchService.isRelevant(RadioSearchRequest.class));
}

@Test
void isRelevant_otherSearchRequest() {
assertFalse(radioSearchService.isRelevant(SonosSearchRequest.class));
}

@Test
void search_songCanBeFound() {
String artist = "Great artist";
String title = "Amazing song";
doReturn(new SongInfo("raw", artist, title)).when(icyReader).currentlyPlaying();
Optional<Song> optionalSong = radioSearchService.search(new RadioSearchRequest("validUrl"));
assertTrue(optionalSong.isPresent());
Song song = optionalSong.get();
assertEquals(artist, song.artist());
assertEquals(title, song.title());
}

@Test
void search_songCannotBeFound() {
doReturn(null).when(icyReader).currentlyPlaying();
Optional<Song> optionalSong = radioSearchService.search(new RadioSearchRequest("validUrl"));
assertTrue(optionalSong.isEmpty());
}

@Test
void search_songWithOnlyRawData() {
doReturn(new SongInfo("rawData", null, null)).when(icyReader).currentlyPlaying();
Optional<Song> optionalSong = radioSearchService.search(new RadioSearchRequest("validUrl"));
assertTrue(optionalSong.isEmpty());
}
}