diff --git a/core-database/src/androidTest/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDaoTest.kt b/core-database/src/androidTest/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDaoTest.kt index dbde3eade..614e2dcd8 100644 --- a/core-database/src/androidTest/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDaoTest.kt +++ b/core-database/src/androidTest/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDaoTest.kt @@ -151,20 +151,20 @@ class NewsResourceDaoTest { newsResourceTopicCrossRefEntities ) - val filteredNewsResources = newsResourceDao.getNewsResourcesForTopicsStream( + val filteredNewsResources = newsResourceDao.getNewsResourcesStream( filterTopicIds = topicEntities .map(TopicEntity::id) - .toSet() + .toSet(), ).first() assertEquals( - listOf(1, 2), + listOf(1, 0), filteredNewsResources.map { it.entity.id } ) } @Test - fun newsResourceDao_filters_items_by_author_topics_ids_by_descending_publish_date() = runTest { + fun newsResourceDao_filters_items_by_author_ids_by_descending_publish_date() = runTest { val authorEntities = listOf( testAuthorEntity( id = 1, @@ -208,7 +208,7 @@ class NewsResourceDaoTest { newsResourceDao.upsertNewsResources(newsResourceEntities) newsResourceDao.insertOrIgnoreAuthorCrossRefEntities(newsResourceAuthorCrossRefEntities) - val filteredNewsResources = newsResourceDao.getNewsResourcesForAuthorsStream( + val filteredNewsResources = newsResourceDao.getNewsResourcesStream( filterAuthorIds = authorEntities .map(AuthorEntity::id) .toSet() @@ -219,6 +219,92 @@ class NewsResourceDaoTest { filteredNewsResources.map { it.entity.id } ) } + + @Test + fun newsResourceDao_filters_items_by_topic_ids_or_author_ids_by_descending_publish_date() = + runTest { + val topicEntities = listOf( + testTopicEntity( + id = 1, + name = "1" + ), + testTopicEntity( + id = 2, + name = "2" + ), + ) + val authorEntities = listOf( + testAuthorEntity( + id = 1, + name = "1" + ), + testAuthorEntity( + id = 2, + name = "2" + ), + ) + val newsResourceEntities = listOf( + testNewsResource( + id = 0, + millisSinceEpoch = 0, + ), + testNewsResource( + id = 1, + millisSinceEpoch = 3, + ), + testNewsResource( + id = 2, + millisSinceEpoch = 1, + ), + testNewsResource( + id = 3, + millisSinceEpoch = 2, + ), + // Should be missing as no topics or authors match it + testNewsResource( + id = 4, + millisSinceEpoch = 10, + ), + ) + val episodeEntityShells = newsResourceEntities + .map(NewsResourceEntity::episodeEntityShell) + .distinct() + val newsResourceTopicCrossRefEntities = topicEntities.mapIndexed { index, topicEntity -> + NewsResourceTopicCrossRef( + newsResourceId = index, + topicId = topicEntity.id + ) + } + val newsResourceAuthorCrossRefEntities = + authorEntities.mapIndexed { index, authorEntity -> + NewsResourceAuthorCrossRef( + // Offset news resources by two + newsResourceId = index + 2, + authorId = authorEntity.id + ) + } + + topicDao.upsertTopics(topicEntities) + authorDao.upsertAuthors(authorEntities) + episodeDao.upsertEpisodes(episodeEntityShells) + newsResourceDao.upsertNewsResources(newsResourceEntities) + newsResourceDao.insertOrIgnoreTopicCrossRefEntities(newsResourceTopicCrossRefEntities) + newsResourceDao.insertOrIgnoreAuthorCrossRefEntities(newsResourceAuthorCrossRefEntities) + + val filteredNewsResources = newsResourceDao.getNewsResourcesStream( + filterTopicIds = topicEntities + .map(TopicEntity::id) + .toSet(), + filterAuthorIds = authorEntities + .map(AuthorEntity::id) + .toSet() + ).first() + + assertEquals( + listOf(1, 3, 2, 0), + filteredNewsResources.map { it.entity.id } + ) + } } private fun testAuthorEntity( diff --git a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDao.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDao.kt index 44adb67fb..d3f615cf0 100644 --- a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDao.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDao.kt @@ -50,45 +50,17 @@ interface NewsResourceDao { SELECT news_resource_id FROM news_resources_topics WHERE topic_id IN (:filterTopicIds) ) - ORDER BY publish_date DESC - """ - ) - fun getNewsResourcesForTopicsStream( - filterTopicIds: Set - ): Flow> - - @Query( - value = """ - SELECT * FROM news_resources - WHERE id in + OR id in ( SELECT news_resource_id FROM news_resources_authors - WHERE author_id IN (:filterAuthorIds) - ) - ORDER BY publish_date DESC - """ - ) - fun getNewsResourcesForAuthorsStream( - filterAuthorIds: Set - ): Flow> - - @Query( - value = """ - SELECT * FROM news_resources - WHERE id in - ( - SELECT topics.topic_id FROM news_resources_topics as topics - INNER JOIN news_resources_authors as authors - ON topics.news_resource_id == authors.news_resource_id - WHERE topics.topic_id IN (:filterTopicIds) - AND authors.author_id IN (:filterAuthorIds) + WHERE author_id IN (:filterAuthorIds) ) ORDER BY publish_date DESC """ ) fun getNewsResourcesStream( - filterAuthorIds: Set, - filterTopicIds: Set + filterAuthorIds: Set = emptySet(), + filterTopicIds: Set = emptySet(), ): Flow> /** diff --git a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/LocalNewsRepository.kt b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/LocalNewsRepository.kt index e6f9a5e9a..8e549a8ba 100644 --- a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/LocalNewsRepository.kt +++ b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/LocalNewsRepository.kt @@ -60,17 +60,10 @@ class LocalNewsRepository @Inject constructor( override fun getNewsResourcesStream( filterAuthorIds: Set, filterTopicIds: Set - ): Flow> = when { - filterAuthorIds.isEmpty() -> { - newsResourceDao.getNewsResourcesForTopicsStream(filterTopicIds) - } - filterTopicIds.isEmpty() -> { - newsResourceDao.getNewsResourcesForAuthorsStream(filterAuthorIds) - } - else -> { - newsResourceDao.getNewsResourcesStream(filterAuthorIds, filterTopicIds) - } - } + ): Flow> = newsResourceDao.getNewsResourcesStream( + filterAuthorIds = filterAuthorIds, + filterTopicIds = filterTopicIds + ) .map { it.map(PopulatedNewsResource::asExternalModel) } override suspend fun sync() = changeListSync( diff --git a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/NewsRepository.kt b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/NewsRepository.kt index ac71f4387..96da2685c 100644 --- a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/NewsRepository.kt +++ b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/NewsRepository.kt @@ -29,11 +29,11 @@ interface NewsRepository { fun getNewsResourcesStream(): Flow> /** - * Returns available news resources as a stream filtered by authors and topics. + * Returns available news resources as a stream filtered by authors or topics. */ fun getNewsResourcesStream( - filterAuthorIds: Set, - filterTopicIds: Set, + filterAuthorIds: Set = emptySet(), + filterTopicIds: Set = emptySet(), ): Flow> /** diff --git a/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/repository/LocalNewsRepositoryTest.kt b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/repository/LocalNewsRepositoryTest.kt index 289624ea2..d20acc592 100644 --- a/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/repository/LocalNewsRepositoryTest.kt +++ b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/repository/LocalNewsRepositoryTest.kt @@ -104,12 +104,13 @@ class LocalNewsRepositoryTest { fun localNewsRepository_news_resources_topic_filtered_stream_is_backed_by_news_resource_dao() = runTest { assertEquals( - newsResourceDao.getNewsResourcesForTopicsStream(filteredInterestsIds) + newsResourceDao.getNewsResourcesStream( + filterTopicIds = filteredInterestsIds, + ) .first() .map(PopulatedNewsResource::asExternalModel), subject.getNewsResourcesStream( filterTopicIds = filteredInterestsIds, - filterAuthorIds = emptySet() ) .first() ) @@ -118,7 +119,6 @@ class LocalNewsRepositoryTest { emptyList(), subject.getNewsResourcesStream( filterTopicIds = nonPresentInterestsIds, - filterAuthorIds = emptySet() ) .first() ) @@ -128,11 +128,12 @@ class LocalNewsRepositoryTest { fun localNewsRepository_news_resources_author_filtered_stream_is_backed_by_news_resource_dao() = runTest { assertEquals( - newsResourceDao.getNewsResourcesForAuthorsStream(filteredInterestsIds) + newsResourceDao.getNewsResourcesStream( + filterAuthorIds = filteredInterestsIds + ) .first() .map(PopulatedNewsResource::asExternalModel), subject.getNewsResourcesStream( - filterTopicIds = emptySet(), filterAuthorIds = filteredInterestsIds ) .first() @@ -141,7 +142,6 @@ class LocalNewsRepositoryTest { assertEquals( emptyList(), subject.getNewsResourcesStream( - filterTopicIds = emptySet(), filterAuthorIds = nonPresentInterestsIds ) .first() diff --git a/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/testdoubles/TestNewsResourceDao.kt b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/testdoubles/TestNewsResourceDao.kt index b911361bf..9d850efbc 100644 --- a/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/testdoubles/TestNewsResourceDao.kt +++ b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/testdoubles/TestNewsResourceDao.kt @@ -74,22 +74,6 @@ class TestNewsResourceDao : NewsResourceDao { } } - override fun getNewsResourcesForTopicsStream( - filterTopicIds: Set - ): Flow> = - getNewsResourcesStream() - .map { resources -> - resources.filter { resource -> resource.topics.any { it.id in filterTopicIds } } - } - - override fun getNewsResourcesForAuthorsStream( - filterAuthorIds: Set - ): Flow> = - getNewsResourcesStream() - .map { resources -> - resources.filter { resource -> resource.authors.any { it.id in filterAuthorIds } } - } - override suspend fun insertOrIgnoreNewsResources( entities: List ): List {