commit
2c9fcebab6
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.database.model
|
||||||
|
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import androidx.room.Junction
|
||||||
|
import androidx.room.Relation
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.Episode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External data layer representation of an NiA episode
|
||||||
|
*/
|
||||||
|
data class PopulatedEpisode(
|
||||||
|
@Embedded
|
||||||
|
val entity: EpisodeEntity,
|
||||||
|
@Relation(
|
||||||
|
parentColumn = "id",
|
||||||
|
entityColumn = "episode_id"
|
||||||
|
)
|
||||||
|
val newsResources: List<NewsResourceEntity>,
|
||||||
|
@Relation(
|
||||||
|
parentColumn = "id",
|
||||||
|
entityColumn = "id",
|
||||||
|
associateBy = Junction(
|
||||||
|
value = EpisodeAuthorCrossRef::class,
|
||||||
|
parentColumn = "episode_id",
|
||||||
|
entityColumn = "author_id",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val authors: List<AuthorEntity>
|
||||||
|
)
|
||||||
|
|
||||||
|
fun PopulatedEpisode.asExternalModel() = Episode(
|
||||||
|
id = entity.id,
|
||||||
|
name = entity.name,
|
||||||
|
publishDate = entity.publishDate,
|
||||||
|
alternateVideo = entity.alternateVideo,
|
||||||
|
alternateAudio = entity.alternateAudio,
|
||||||
|
newsResources = newsResources.map(NewsResourceEntity::asExternalModel),
|
||||||
|
authors = authors.map(AuthorEntity::asExternalModel)
|
||||||
|
)
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.database.model
|
||||||
|
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import androidx.room.Junction
|
||||||
|
import androidx.room.Relation
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External data layer representation of a fully populated NiA news resource
|
||||||
|
*/
|
||||||
|
data class PopulatedNewsResource(
|
||||||
|
@Embedded
|
||||||
|
val entity: NewsResourceEntity,
|
||||||
|
@Relation(
|
||||||
|
parentColumn = "episode_id",
|
||||||
|
entityColumn = "id"
|
||||||
|
)
|
||||||
|
val episode: EpisodeEntity,
|
||||||
|
@Relation(
|
||||||
|
parentColumn = "id",
|
||||||
|
entityColumn = "id",
|
||||||
|
associateBy = Junction(
|
||||||
|
value = NewsResourceAuthorCrossRef::class,
|
||||||
|
parentColumn = "news_resource_id",
|
||||||
|
entityColumn = "author_id",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val authors: List<AuthorEntity>,
|
||||||
|
@Relation(
|
||||||
|
parentColumn = "id",
|
||||||
|
entityColumn = "id",
|
||||||
|
associateBy = Junction(
|
||||||
|
value = NewsResourceTopicCrossRef::class,
|
||||||
|
parentColumn = "news_resource_id",
|
||||||
|
entityColumn = "topic_id",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val topics: List<TopicEntity>
|
||||||
|
)
|
||||||
|
|
||||||
|
fun PopulatedNewsResource.asExternalModel() = NewsResource(
|
||||||
|
id = entity.id,
|
||||||
|
episodeId = entity.episodeId,
|
||||||
|
title = entity.title,
|
||||||
|
content = entity.content,
|
||||||
|
url = entity.url,
|
||||||
|
publishDate = entity.publishDate,
|
||||||
|
type = entity.type,
|
||||||
|
authors = authors.map(AuthorEntity::asExternalModel),
|
||||||
|
topics = topics.map(TopicEntity::asExternalModel)
|
||||||
|
)
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.domain.model
|
||||||
|
|
||||||
|
import com.google.samples.apps.nowinandroid.core.database.model.AuthorEntity
|
||||||
|
import com.google.samples.apps.nowinandroid.core.network.model.NetworkAuthor
|
||||||
|
|
||||||
|
fun NetworkAuthor.asEntity() = AuthorEntity(
|
||||||
|
id = id,
|
||||||
|
name = name,
|
||||||
|
imageUrl = imageUrl
|
||||||
|
)
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.domain.model
|
||||||
|
|
||||||
|
import com.google.samples.apps.nowinandroid.core.database.model.EpisodeEntity
|
||||||
|
import com.google.samples.apps.nowinandroid.core.network.model.NetworkEpisode
|
||||||
|
import com.google.samples.apps.nowinandroid.core.network.model.NetworkEpisodeExpanded
|
||||||
|
|
||||||
|
fun NetworkEpisode.asEntity() = EpisodeEntity(
|
||||||
|
id = id,
|
||||||
|
name = name,
|
||||||
|
publishDate = publishDate,
|
||||||
|
alternateVideo = alternateVideo,
|
||||||
|
alternateAudio = alternateAudio,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun NetworkEpisodeExpanded.asEntity() = EpisodeEntity(
|
||||||
|
id = id,
|
||||||
|
name = name,
|
||||||
|
publishDate = publishDate,
|
||||||
|
alternateVideo = alternateVideo,
|
||||||
|
alternateAudio = alternateAudio,
|
||||||
|
)
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.domain.model
|
||||||
|
|
||||||
|
import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceEntity
|
||||||
|
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
|
||||||
|
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResourceExpanded
|
||||||
|
|
||||||
|
fun NetworkNewsResource.asEntity() = NewsResourceEntity(
|
||||||
|
id = id,
|
||||||
|
episodeId = episodeId,
|
||||||
|
title = title,
|
||||||
|
content = content,
|
||||||
|
url = url,
|
||||||
|
publishDate = publishDate,
|
||||||
|
type = type,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun NetworkNewsResourceExpanded.asEntity() = NewsResourceEntity(
|
||||||
|
id = id,
|
||||||
|
episodeId = episodeId,
|
||||||
|
title = title,
|
||||||
|
content = content,
|
||||||
|
url = url,
|
||||||
|
publishDate = publishDate,
|
||||||
|
type = type,
|
||||||
|
)
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.domain.model
|
||||||
|
|
||||||
|
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
|
||||||
|
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
|
||||||
|
|
||||||
|
fun NetworkTopic.asEntity() = TopicEntity(
|
||||||
|
id = id,
|
||||||
|
name = name,
|
||||||
|
description = description,
|
||||||
|
followed = followed
|
||||||
|
)
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.database.model
|
||||||
|
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.Author
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.Episode
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Video
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class PopulatedEpisodeKtTest {
|
||||||
|
@Test
|
||||||
|
fun populated_episode_can_be_mapped_to_episode() {
|
||||||
|
val populatedEpisode = PopulatedEpisode(
|
||||||
|
entity = EpisodeEntity(
|
||||||
|
id = 0,
|
||||||
|
name = "Test",
|
||||||
|
publishDate = Instant.fromEpochMilliseconds(1),
|
||||||
|
alternateAudio = "audio",
|
||||||
|
alternateVideo = "video"
|
||||||
|
),
|
||||||
|
newsResources = listOf(
|
||||||
|
NewsResourceEntity(
|
||||||
|
id = 1,
|
||||||
|
episodeId = 0,
|
||||||
|
title = "news",
|
||||||
|
content = "Hilt",
|
||||||
|
url = "url",
|
||||||
|
type = Video,
|
||||||
|
publishDate = Instant.fromEpochMilliseconds(1),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
authors = listOf(
|
||||||
|
AuthorEntity(
|
||||||
|
id = 2,
|
||||||
|
name = "name",
|
||||||
|
imageUrl = "imageUrl"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val episode = populatedEpisode.asExternalModel()
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
Episode(
|
||||||
|
id = 0,
|
||||||
|
name = "Test",
|
||||||
|
publishDate = Instant.fromEpochMilliseconds(1),
|
||||||
|
alternateAudio = "audio",
|
||||||
|
alternateVideo = "video",
|
||||||
|
newsResources = listOf(
|
||||||
|
NewsResource(
|
||||||
|
id = 1,
|
||||||
|
episodeId = 0,
|
||||||
|
title = "news",
|
||||||
|
content = "Hilt",
|
||||||
|
url = "url",
|
||||||
|
type = Video,
|
||||||
|
publishDate = Instant.fromEpochMilliseconds(1),
|
||||||
|
authors = listOf(),
|
||||||
|
topics = listOf()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
authors = listOf(
|
||||||
|
Author(
|
||||||
|
id = 2,
|
||||||
|
name = "name",
|
||||||
|
imageUrl = "imageUrl"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
episode
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.database.model
|
||||||
|
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.Author
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Video
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.Topic
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class PopulatedNewsResourceKtTest {
|
||||||
|
@Test
|
||||||
|
fun populated_news_resource_can_be_mapped_to_news_resource() {
|
||||||
|
val populatedNewsResource = PopulatedNewsResource(
|
||||||
|
entity = NewsResourceEntity(
|
||||||
|
id = 1,
|
||||||
|
episodeId = 0,
|
||||||
|
title = "news",
|
||||||
|
content = "Hilt",
|
||||||
|
url = "url",
|
||||||
|
type = Video,
|
||||||
|
publishDate = Instant.fromEpochMilliseconds(1),
|
||||||
|
),
|
||||||
|
episode = EpisodeEntity(
|
||||||
|
id = 4,
|
||||||
|
name = "episode 4",
|
||||||
|
publishDate = Instant.fromEpochMilliseconds(2),
|
||||||
|
alternateAudio = "audio",
|
||||||
|
alternateVideo = "video",
|
||||||
|
),
|
||||||
|
authors = listOf(
|
||||||
|
AuthorEntity(
|
||||||
|
id = 2,
|
||||||
|
name = "name",
|
||||||
|
imageUrl = "imageUrl"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
topics = listOf(
|
||||||
|
TopicEntity(
|
||||||
|
id = 3,
|
||||||
|
name = "name",
|
||||||
|
description = "description",
|
||||||
|
followed = true,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val newsResource = populatedNewsResource.asExternalModel()
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
NewsResource(
|
||||||
|
id = 1,
|
||||||
|
episodeId = 0,
|
||||||
|
title = "news",
|
||||||
|
content = "Hilt",
|
||||||
|
url = "url",
|
||||||
|
type = Video,
|
||||||
|
publishDate = Instant.fromEpochMilliseconds(1),
|
||||||
|
authors = listOf(
|
||||||
|
Author(
|
||||||
|
id = 2,
|
||||||
|
name = "name",
|
||||||
|
imageUrl = "imageUrl"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
topics = listOf(
|
||||||
|
Topic(
|
||||||
|
id = 3,
|
||||||
|
name = "name",
|
||||||
|
description = "description",
|
||||||
|
followed = true,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
newsResource
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.model.data
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External data layer representation of an NiA Author
|
||||||
|
*/
|
||||||
|
data class Author(
|
||||||
|
val id: Int,
|
||||||
|
val name: String,
|
||||||
|
val imageUrl: String,
|
||||||
|
)
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.core.network.model.util
|
||||||
|
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType
|
||||||
|
import com.google.samples.apps.nowinandroid.core.model.data.asNewsResourceType
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveKind.STRING
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
|
||||||
|
object NewsResourceTypeSerializer : KSerializer<NewsResourceType> {
|
||||||
|
override fun deserialize(decoder: Decoder): NewsResourceType =
|
||||||
|
decoder.decodeString().asNewsResourceType()
|
||||||
|
|
||||||
|
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(
|
||||||
|
serialName = "type",
|
||||||
|
kind = STRING
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: NewsResourceType) =
|
||||||
|
encoder.encodeString(value.name)
|
||||||
|
}
|
Loading…
Reference in new issue