Make Ids composite of Item Id + Server Id

This commit is contained in:
tzugen 2022-07-04 17:31:58 +02:00
parent 177329abcf
commit ad54db5bcb
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
29 changed files with 870 additions and 153 deletions

View File

@ -1,12 +1,22 @@
/*
* Album.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.domain
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.Date
@Entity(tableName = "albums")
@Entity(tableName = "albums", primaryKeys = ["id", "serverId"])
data class Album(
@PrimaryKey override var id: String,
override var id: String,
@ColumnInfo(defaultValue = "-1")
override var serverId: Int = -1,
override var parent: String? = null,
override var album: String? = null,
override var title: String? = null,

View File

@ -1,14 +1,24 @@
/*
* Artist.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.domain
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "artists")
@Entity(tableName = "artists", primaryKeys = ["id", "serverId"])
data class Artist(
@PrimaryKey override var id: String,
override var id: String,
@ColumnInfo(defaultValue = "-1")
override var serverId: Int = -1,
override var name: String? = null,
override var index: String? = null,
override var coverArt: String? = null,
override var albumCount: Long? = null,
override var closeness: Int = 0
) : ArtistOrIndex(id)
) : ArtistOrIndex(id, serverId)

View File

@ -1,3 +1,10 @@
/*
* ArtistOrIndex.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.domain
import androidx.room.Ignore
@ -6,6 +13,8 @@ abstract class ArtistOrIndex(
@Ignore
override var id: String,
@Ignore
open var serverId: Int,
@Ignore
override var name: String? = null,
@Ignore
open var index: String? = null,
@ -18,15 +27,15 @@ abstract class ArtistOrIndex(
) : GenericEntry() {
fun compareTo(other: ArtistOrIndex): Int {
when {
return when {
this.closeness == other.closeness -> {
return 0
0
}
this.closeness > other.closeness -> {
return -1
-1
}
else -> {
return 1
1
}
}
}

View File

@ -1,15 +1,25 @@
/*
* Index.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.domain
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "indexes")
@Entity(tableName = "indexes", primaryKeys = ["id", "serverId"])
data class Index(
@PrimaryKey override var id: String,
override var id: String,
@ColumnInfo(defaultValue = "-1")
override var serverId: Int = -1,
override var name: String? = null,
override var index: String? = null,
override var coverArt: String? = null,
override var albumCount: Long? = null,
override var closeness: Int = 0,
var musicFolderId: String? = null
) : ArtistOrIndex(id)
) : ArtistOrIndex(id, serverId)

View File

@ -1,3 +1,10 @@
/*
* MusicDirectory.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.domain
import java.util.Date
@ -31,6 +38,7 @@ class MusicDirectory : ArrayList<MusicDirectory.Child>() {
abstract class Child : GenericEntry() {
abstract override var id: String
abstract var serverId: Int
abstract var parent: String?
abstract var isDirectory: Boolean
abstract var album: String?

View File

@ -1,13 +1,22 @@
/*
* MusicFolder.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.domain
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
/**
* Represents a top level directory in which music or other media is stored.
*/
@Entity(tableName = "music_folders")
@Entity(tableName = "music_folders", primaryKeys = ["id", "serverId"])
data class MusicFolder(
@PrimaryKey override val id: String,
override val name: String
override val id: String,
override val name: String,
@ColumnInfo(defaultValue = "-1")
var serverId: Int
) : GenericEntry()

View File

@ -1,13 +1,23 @@
/*
* Track.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.domain
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.io.Serializable
import java.util.Date
@Entity(tableName = "tracks")
@Entity(tableName = "tracks", primaryKeys = ["id", "serverId"])
data class Track(
@PrimaryKey override var id: String,
override var id: String,
@ColumnInfo(defaultValue = "-1")
override var serverId: Int = -1,
override var parent: String? = null,
override var isDirectory: Boolean = false,
override var title: String? = null,

View File

@ -0,0 +1,514 @@
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "95e83d6663a862c03ac46f9567453ded",
"entities": [
{
"tableName": "artists",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, `name` TEXT, `index` TEXT, `coverArt` TEXT, `albumCount` INTEGER, `closeness` INTEGER NOT NULL, PRIMARY KEY(`id`, `serverId`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "-1"
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "index",
"columnName": "index",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "coverArt",
"columnName": "coverArt",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "albumCount",
"columnName": "albumCount",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "closeness",
"columnName": "closeness",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id",
"serverId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "albums",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, `parent` TEXT, `album` TEXT, `title` TEXT, `name` TEXT, `discNumber` INTEGER, `coverArt` TEXT, `songCount` INTEGER, `created` INTEGER, `artist` TEXT, `artistId` TEXT, `duration` INTEGER, `year` INTEGER, `genre` TEXT, `starred` INTEGER NOT NULL, `path` TEXT, `closeness` INTEGER NOT NULL, `isDirectory` INTEGER NOT NULL, `isVideo` INTEGER NOT NULL, PRIMARY KEY(`id`, `serverId`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "-1"
},
{
"fieldPath": "parent",
"columnName": "parent",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "album",
"columnName": "album",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "discNumber",
"columnName": "discNumber",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "coverArt",
"columnName": "coverArt",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "songCount",
"columnName": "songCount",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "created",
"columnName": "created",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "artist",
"columnName": "artist",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "artistId",
"columnName": "artistId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "year",
"columnName": "year",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "genre",
"columnName": "genre",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "starred",
"columnName": "starred",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "path",
"columnName": "path",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "closeness",
"columnName": "closeness",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "isDirectory",
"columnName": "isDirectory",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "isVideo",
"columnName": "isVideo",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id",
"serverId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "tracks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, `parent` TEXT, `isDirectory` INTEGER NOT NULL, `title` TEXT, `album` TEXT, `albumId` TEXT, `artist` TEXT, `artistId` TEXT, `track` INTEGER, `year` INTEGER, `genre` TEXT, `contentType` TEXT, `suffix` TEXT, `transcodedContentType` TEXT, `transcodedSuffix` TEXT, `coverArt` TEXT, `size` INTEGER, `songCount` INTEGER, `duration` INTEGER, `bitRate` INTEGER, `path` TEXT, `isVideo` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `discNumber` INTEGER, `type` TEXT, `created` INTEGER, `closeness` INTEGER NOT NULL, `bookmarkPosition` INTEGER NOT NULL, `userRating` INTEGER, `averageRating` REAL, `name` TEXT, PRIMARY KEY(`id`, `serverId`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "-1"
},
{
"fieldPath": "parent",
"columnName": "parent",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "isDirectory",
"columnName": "isDirectory",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "album",
"columnName": "album",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "albumId",
"columnName": "albumId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "artist",
"columnName": "artist",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "artistId",
"columnName": "artistId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "track",
"columnName": "track",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "year",
"columnName": "year",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "genre",
"columnName": "genre",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "contentType",
"columnName": "contentType",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "suffix",
"columnName": "suffix",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "transcodedContentType",
"columnName": "transcodedContentType",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "transcodedSuffix",
"columnName": "transcodedSuffix",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "coverArt",
"columnName": "coverArt",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "size",
"columnName": "size",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "songCount",
"columnName": "songCount",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "bitRate",
"columnName": "bitRate",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "path",
"columnName": "path",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "isVideo",
"columnName": "isVideo",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "starred",
"columnName": "starred",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "discNumber",
"columnName": "discNumber",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "created",
"columnName": "created",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "closeness",
"columnName": "closeness",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "bookmarkPosition",
"columnName": "bookmarkPosition",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "userRating",
"columnName": "userRating",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "averageRating",
"columnName": "averageRating",
"affinity": "REAL",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id",
"serverId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "indexes",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, `name` TEXT, `index` TEXT, `coverArt` TEXT, `albumCount` INTEGER, `closeness` INTEGER NOT NULL, `musicFolderId` TEXT, PRIMARY KEY(`id`, `serverId`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "-1"
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "index",
"columnName": "index",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "coverArt",
"columnName": "coverArt",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "albumCount",
"columnName": "albumCount",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "closeness",
"columnName": "closeness",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "musicFolderId",
"columnName": "musicFolderId",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id",
"serverId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "music_folders",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, `name` TEXT NOT NULL, PRIMARY KEY(`id`, `serverId`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "-1"
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id",
"serverId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '95e83d6663a862c03ac46f9567453ded')"
]
}
}

View File

@ -1,3 +1,10 @@
/*
* ActiveServerProvider.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.data
import androidx.room.Room
@ -124,7 +131,9 @@ class ActiveServerProvider(
UApp.applicationContext(),
MetaDatabase::class.java,
METADATA_DB + serverId
).fallbackToDestructiveMigrationOnDowngrade()
)
.addMigrations(META_MIGRATION_2_3)
.fallbackToDestructiveMigrationOnDowngrade()
.build()
}

View File

@ -1,3 +1,10 @@
/*
* MetaDatabase.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.data
import androidx.room.AutoMigration
@ -5,12 +12,14 @@ import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverter
import androidx.room.TypeConverters
import java.util.Date
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import org.moire.ultrasonic.domain.Album
import org.moire.ultrasonic.domain.Artist
import org.moire.ultrasonic.domain.Index
import org.moire.ultrasonic.domain.MusicFolder
import org.moire.ultrasonic.domain.Track
import java.util.Date
/**
* This database is used to store and cache the ID3 metadata
@ -31,7 +40,7 @@ import org.moire.ultrasonic.domain.Track
),
],
exportSchema = true,
version = 2
version = 3
)
@TypeConverters(Converters::class)
abstract class MetaDatabase : RoomDatabase() {
@ -57,3 +66,18 @@ class Converters {
return date?.time
}
}
val META_MIGRATION_2_3: Migration = object : Migration(2,3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE `albums`")
database.execSQL("DROP TABLE `indexes`")
database.execSQL("DROP TABLE `artists`")
database.execSQL("DROP TABLE `tracks`")
database.execSQL("DROP TABLE `music_folders`")
database.execSQL("CREATE TABLE IF NOT EXISTS `albums` (`id` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, `parent` TEXT, `album` TEXT, `title` TEXT, `name` TEXT, `discNumber` INTEGER, `coverArt` TEXT, `songCount` INTEGER, `created` INTEGER, `artist` TEXT, `artistId` TEXT, `duration` INTEGER, `year` INTEGER, `genre` TEXT, `starred` INTEGER NOT NULL, `path` TEXT, `closeness` INTEGER NOT NULL, `isDirectory` INTEGER NOT NULL, `isVideo` INTEGER NOT NULL, PRIMARY KEY(`id`, `serverId`))")
database.execSQL("CREATE TABLE IF NOT EXISTS `indexes` (`id` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, `name` TEXT, `index` TEXT, `coverArt` TEXT, `albumCount` INTEGER, `closeness` INTEGER NOT NULL, `musicFolderId` TEXT, PRIMARY KEY(`id`, `serverId`))")
database.execSQL("CREATE TABLE IF NOT EXISTS `artists` (`id` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, `name` TEXT, `index` TEXT, `coverArt` TEXT, `albumCount` INTEGER, `closeness` INTEGER NOT NULL, PRIMARY KEY(`id`, `serverId`))")
database.execSQL("CREATE TABLE IF NOT EXISTS `music_folders` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, PRIMARY KEY(`id`, `serverId`))")
database.execSQL("CREATE TABLE IF NOT EXISTS `tracks` (`id` TEXT NOT NULL, `serverId` INTEGER NOT NULL DEFAULT -1, `parent` TEXT, `isDirectory` INTEGER NOT NULL, `title` TEXT, `album` TEXT, `albumId` TEXT, `artist` TEXT, `artistId` TEXT, `track` INTEGER, `year` INTEGER, `genre` TEXT, `contentType` TEXT, `suffix` TEXT, `transcodedContentType` TEXT, `transcodedSuffix` TEXT, `coverArt` TEXT, `size` INTEGER, `songCount` INTEGER, `duration` INTEGER, `bitRate` INTEGER, `path` TEXT, `isVideo` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `discNumber` INTEGER, `type` TEXT, `created` INTEGER, `closeness` INTEGER NOT NULL, `bookmarkPosition` INTEGER NOT NULL, `userRating` INTEGER, `averageRating` REAL, `name` TEXT, PRIMARY KEY(`id`, `serverId`))")
}
}

View File

@ -1,3 +1,10 @@
/*
* APIAlbumConverter.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
// Converts Album entity from [org.moire.ultrasonic.api.subsonic.SubsonicAPIClient]
// to app domain entities.
@file:JvmName("APIAlbumConverter")
@ -6,8 +13,9 @@ package org.moire.ultrasonic.domain
import org.moire.ultrasonic.api.subsonic.models.Album
typealias DomainAlbum = org.moire.ultrasonic.domain.Album
fun Album.toDomainEntity(): DomainAlbum = Album(
fun Album.toDomainEntity(serverId: Int): DomainAlbum = Album(
id = this@toDomainEntity.id,
serverId = serverId,
title = this@toDomainEntity.name ?: this@toDomainEntity.title,
album = this@toDomainEntity.album,
coverArt = this@toDomainEntity.coverArt,
@ -21,8 +29,10 @@ fun Album.toDomainEntity(): DomainAlbum = Album(
starred = this@toDomainEntity.starredDate.isNotEmpty()
)
fun Album.toMusicDirectoryDomainEntity(): MusicDirectory = MusicDirectory().apply {
addAll(this@toMusicDirectoryDomainEntity.songList.map { it.toTrackEntity() })
fun Album.toMusicDirectoryDomainEntity(serverId: Int): MusicDirectory = MusicDirectory().apply {
addAll(this@toMusicDirectoryDomainEntity.songList.map { it.toTrackEntity(serverId) })
}
fun List<Album>.toDomainEntityList(): List<DomainAlbum> = this.map { it.toDomainEntity() }
fun List<Album>.toDomainEntityList(serverId: Int): List<DomainAlbum> = this.map {
it.toDomainEntity(serverId)
}

View File

@ -1,3 +1,10 @@
/*
* APIArtistConverter.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
// Converts Artist entity from [org.moire.ultrasonic.api.subsonic.SubsonicAPIClient]
// to app domain entities.
@file:JvmName("APIArtistConverter")
@ -6,24 +13,26 @@ package org.moire.ultrasonic.domain
import org.moire.ultrasonic.api.subsonic.models.Artist as APIArtist
// When we like to convert to an Artist
fun APIArtist.toDomainEntity(): Artist = Artist(
fun APIArtist.toDomainEntity(serverId: Int): Artist = Artist(
id = this@toDomainEntity.id,
serverId = serverId,
coverArt = this@toDomainEntity.coverArt,
name = this@toDomainEntity.name
)
// When we like to convert to an index (eg. a single directory).
fun APIArtist.toIndexEntity(): Index = Index(
fun APIArtist.toIndexEntity(serverId: Int): Index = Index(
id = this@toIndexEntity.id,
serverId = serverId,
coverArt = this@toIndexEntity.coverArt,
name = this@toIndexEntity.name
)
fun APIArtist.toMusicDirectoryDomainEntity(): MusicDirectory = MusicDirectory().apply {
fun APIArtist.toMusicDirectoryDomainEntity(serverId: Int): MusicDirectory = MusicDirectory().apply {
name = this@toMusicDirectoryDomainEntity.name
addAll(this@toMusicDirectoryDomainEntity.albumsList.map { it.toDomainEntity() })
addAll(this@toMusicDirectoryDomainEntity.albumsList.map { it.toDomainEntity(serverId) })
}
fun APIArtist.toDomainEntityList(): List<Album> {
return this.albumsList.map { it.toDomainEntity() }
fun APIArtist.toDomainEntityList(serverId: Int): List<Album> {
return this.albumsList.map { it.toDomainEntity(serverId) }
}

View File

@ -1,16 +1,25 @@
/*
* APIBookmarkConverter.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
// Contains helper functions to convert api Bookmark entity to domain entity
@file:JvmName("APIBookmarkConverter")
package org.moire.ultrasonic.domain
import org.moire.ultrasonic.api.subsonic.models.Bookmark as ApiBookmark
fun ApiBookmark.toDomainEntity(): Bookmark = Bookmark(
fun ApiBookmark.toDomainEntity(serverId: Int): Bookmark = Bookmark(
position = this@toDomainEntity.position.toInt(),
username = this@toDomainEntity.username,
comment = this@toDomainEntity.comment,
created = this@toDomainEntity.created?.time,
changed = this@toDomainEntity.changed?.time,
track = this@toDomainEntity.entry.toTrackEntity()
track = this@toDomainEntity.entry.toTrackEntity(serverId)
)
fun List<ApiBookmark>.toDomainEntitiesList(): List<Bookmark> = map { it.toDomainEntity() }
fun List<ApiBookmark>.toDomainEntitiesList(serverId: Int): List<Bookmark> =
map { it.toDomainEntity(serverId) }

View File

@ -1,14 +1,22 @@
/*
* APIIndexesConverter.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
// Converts Indexes entity from [org.moire.ultrasonic.api.subsonic.SubsonicAPIClient]
// to app domain entities.
@file:JvmName("APIIndexesConverter")
package org.moire.ultrasonic.domain
import org.moire.ultrasonic.api.subsonic.models.Index as APIIndex
import org.moire.ultrasonic.api.subsonic.models.Indexes as APIIndexes
fun APIIndexes.toArtistList(): List<Artist> {
val shortcuts = this.shortcutList.map { it.toDomainEntity() }.toMutableList()
val indexes = this.indexList.foldIndexToArtistList()
fun APIIndexes.toArtistList(serverId: Int): List<Artist> {
val shortcuts = this.shortcutList.map { it.toDomainEntity(serverId) }.toMutableList()
val indexes = this.indexList.foldIndexToArtistList(serverId)
indexes.forEach {
if (!shortcuts.contains(it)) {
@ -19,9 +27,9 @@ fun APIIndexes.toArtistList(): List<Artist> {
return shortcuts
}
fun APIIndexes.toIndexList(musicFolderId: String?): List<Index> {
val shortcuts = this.shortcutList.map { it.toIndexEntity() }.toMutableList()
val indexes = this.indexList.foldIndexToIndexList(musicFolderId)
fun APIIndexes.toIndexList(serverId: Int, musicFolderId: String?): List<Index> {
val shortcuts = this.shortcutList.map { it.toIndexEntity(serverId) }.toMutableList()
val indexes = this.indexList.foldIndexToIndexList(musicFolderId, serverId)
indexes.forEach {
if (!shortcuts.contains(it)) {
@ -32,22 +40,23 @@ fun APIIndexes.toIndexList(musicFolderId: String?): List<Index> {
return shortcuts
}
private fun List<APIIndex>.foldIndexToArtistList(): List<Artist> = this.fold(
listOf(),
{ acc, index ->
acc + index.artists.map {
it.toDomainEntity()
}
private fun List<APIIndex>.foldIndexToArtistList(serverId: Int): List<Artist> = this.fold(
listOf()
) { acc, index ->
acc + index.artists.map {
it.toDomainEntity(serverId)
}
)
}
private fun List<APIIndex>.foldIndexToIndexList(musicFolderId: String?): List<Index> = this.fold(
listOf(),
{ acc, index ->
acc + index.artists.map {
val ret = it.toIndexEntity()
ret.musicFolderId = musicFolderId
ret
}
private fun List<APIIndex>.foldIndexToIndexList(
musicFolderId: String?,
serverId: Int
): List<Index> = this.fold(
listOf()
) { acc, index ->
acc + index.artists.map {
val ret = it.toIndexEntity(serverId)
ret.musicFolderId = musicFolderId
ret
}
)
}

View File

@ -1,6 +1,6 @@
/*
* APIMusicDirectoryConverter.kt
* Copyright (C) 2009-2021 Ultrasonic developers
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
@ -26,12 +26,12 @@ internal val dateFormat: DateFormat by lazy {
SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault())
}
fun MusicDirectoryChild.toTrackEntity(): Track = Track(id).apply {
fun MusicDirectoryChild.toTrackEntity(serverId: Int): Track = Track(id, serverId).apply {
populateCommonProps(this, this@toTrackEntity)
populateTrackProps(this, this@toTrackEntity)
}
fun MusicDirectoryChild.toAlbumEntity(): Album = Album(id).apply {
fun MusicDirectoryChild.toAlbumEntity(serverId: Int): Album = Album(id, serverId).apply {
populateCommonProps(this, this@toAlbumEntity)
}
@ -80,24 +80,24 @@ private fun populateTrackProps(
track.averageRating = source.averageRating
}
fun List<MusicDirectoryChild>.toDomainEntityList(): List<MusicDirectory.Child> {
fun List<MusicDirectoryChild>.toDomainEntityList(serverId: Int): List<MusicDirectory.Child> {
val newList: MutableList<MusicDirectory.Child> = mutableListOf()
forEach {
if (it.isDir)
newList.add(it.toAlbumEntity())
newList.add(it.toAlbumEntity(serverId))
else
newList.add(it.toTrackEntity())
newList.add(it.toTrackEntity(serverId))
}
return newList
}
fun List<MusicDirectoryChild>.toTrackList(): List<Track> = this.map {
it.toTrackEntity()
fun List<MusicDirectoryChild>.toTrackList(serverId: Int): List<Track> = this.map {
it.toTrackEntity(serverId)
}
fun APIMusicDirectory.toDomainEntity(): MusicDirectory = MusicDirectory().apply {
fun APIMusicDirectory.toDomainEntity(serverId: Int): MusicDirectory = MusicDirectory().apply {
name = this@toDomainEntity.name
addAll(this@toDomainEntity.childList.toDomainEntityList())
addAll(this@toDomainEntity.childList.toDomainEntityList(serverId))
}

View File

@ -1,3 +1,10 @@
/*
* APIMusicFolderConverter.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
// Converts MusicFolder entity from [org.moire.ultrasonic.api.subsonic.SubsonicAPIClient]
// to app domain entities.
@file:JvmName("APIMusicFolderConverter")
@ -5,7 +12,15 @@ package org.moire.ultrasonic.domain
import org.moire.ultrasonic.api.subsonic.models.MusicFolder as APIMusicFolder
fun APIMusicFolder.toDomainEntity(): MusicFolder = MusicFolder(this.id, this.name)
fun APIMusicFolder.toDomainEntity(serverId: Int): MusicFolder = MusicFolder(
id = this.id,
serverId = serverId,
name = this.name
)
fun List<APIMusicFolder>.toDomainEntityList(): List<MusicFolder> =
this.map { it.toDomainEntity() }
fun List<APIMusicFolder>.toDomainEntityList(serverId: Int): List<MusicFolder> =
this.map {
val item = it.toDomainEntity(serverId)
item.serverId = serverId
item
}

View File

@ -1,6 +1,14 @@
/*
* APIPlaylistConverter.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
// Converts Playlist entity from [org.moire.ultrasonic.api.subsonic.SubsonicAPIClient]
// to app domain entities.
@file:JvmName("APIPlaylistConverter")
package org.moire.ultrasonic.domain
import java.text.SimpleDateFormat
@ -10,10 +18,15 @@ import org.moire.ultrasonic.util.Util.ifNotNull
internal val playlistDateFormat by lazy(NONE) { SimpleDateFormat.getInstance() }
fun APIPlaylist.toMusicDirectoryDomainEntity(): MusicDirectory = MusicDirectory().apply {
name = this@toMusicDirectoryDomainEntity.name
addAll(this@toMusicDirectoryDomainEntity.entriesList.map { it.toTrackEntity() })
}
fun APIPlaylist.toMusicDirectoryDomainEntity(serverId: Int): MusicDirectory =
MusicDirectory().apply {
name = this@toMusicDirectoryDomainEntity.name
addAll(this@toMusicDirectoryDomainEntity.entriesList.map {
val item = it.toTrackEntity(serverId)
item.serverId = serverId
item
})
}
fun APIPlaylist.toDomainEntity(): Playlist = Playlist(
this.id, this.name, this.owner,

View File

@ -1,3 +1,10 @@
/*
* APISearchConverter.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
// Converts SearchResult entities from [org.moire.ultrasonic.api.subsonic.SubsonicAPIClient]
// to app domain entities.
@file:JvmName("APISearchConverter")
@ -7,19 +14,19 @@ import org.moire.ultrasonic.api.subsonic.models.SearchResult as APISearchResult
import org.moire.ultrasonic.api.subsonic.models.SearchThreeResult
import org.moire.ultrasonic.api.subsonic.models.SearchTwoResult
fun APISearchResult.toDomainEntity(): SearchResult = SearchResult(
fun APISearchResult.toDomainEntity(serverId: Int): SearchResult = SearchResult(
emptyList(), emptyList(),
this.matchList.map { it.toTrackEntity() }
this.matchList.map { it.toTrackEntity(serverId) }
)
fun SearchTwoResult.toDomainEntity(): SearchResult = SearchResult(
this.artistList.map { it.toIndexEntity() },
this.albumList.map { it.toDomainEntity() },
this.songList.map { it.toTrackEntity() }
fun SearchTwoResult.toDomainEntity(serverId: Int): SearchResult = SearchResult(
this.artistList.map { it.toIndexEntity(serverId) },
this.albumList.map { it.toDomainEntity(serverId) },
this.songList.map { it.toTrackEntity(serverId) }
)
fun SearchThreeResult.toDomainEntity(): SearchResult = SearchResult(
this.artistList.map { it.toDomainEntity() },
this.albumList.map { it.toDomainEntity() },
this.songList.map { it.toTrackEntity() }
fun SearchThreeResult.toDomainEntity(serverId: Int): SearchResult = SearchResult(
this.artistList.map { it.toDomainEntity(serverId) },
this.albumList.map { it.toDomainEntity(serverId) },
this.songList.map { it.toTrackEntity(serverId) }
)

View File

@ -1,3 +1,10 @@
/*
* APIShareConverter.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
// Contains helper method to convert subsonic api share to domain model
@file:JvmName("APIShareConverter")
package org.moire.ultrasonic.domain
@ -9,11 +16,11 @@ import org.moire.ultrasonic.util.Util.ifNotNull
internal val shareTimeFormat by lazy(NONE) { SimpleDateFormat.getInstance() }
fun List<APIShare>.toDomainEntitiesList(): List<Share> = this.map {
it.toDomainEntity()
fun List<APIShare>.toDomainEntitiesList(serverId: Int): List<Share> = this.map {
it.toDomainEntity(serverId)
}
fun APIShare.toDomainEntity(): Share = Share(
fun APIShare.toDomainEntity(serverId: Int): Share = Share(
created = this@toDomainEntity.created.ifNotNull { shareTimeFormat.format(it.time) },
description = this@toDomainEntity.description,
expires = this@toDomainEntity.expires.ifNotNull { shareTimeFormat.format(it.time) },
@ -22,5 +29,5 @@ fun APIShare.toDomainEntity(): Share = Share(
url = this@toDomainEntity.url,
username = this@toDomainEntity.username,
visitCount = this@toDomainEntity.visitCount.toLong(),
tracks = this@toDomainEntity.items.toTrackList().toMutableList()
tracks = this@toDomainEntity.items.toTrackList(serverId).toMutableList()
)

View File

@ -1,6 +1,6 @@
/*
* OfflineMusicService.kt
* Copyright (C) 2009-2021 Ultrasonic developers
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
@ -66,7 +66,7 @@ class OfflineMusicService : MusicService, KoinComponent {
val root = FileUtil.musicDirectory
for (file in FileUtil.listFiles(root)) {
if (file.isDirectory) {
val index = Index(file.path)
val index = Index(id = file.path)
index.id = file.path
index.index = file.name.substring(0, 1)
index.name = file.name

View File

@ -1,6 +1,6 @@
/*
* RestMusicService.kt
* Copyright (C) 2009-2021 Ultrasonic developers
* RESTMusicService.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
@ -78,7 +78,7 @@ open class RESTMusicService(
): List<MusicFolder> {
val response = API.getMusicFolders().execute().throwOnFailure()
return response.body()!!.musicFolders.toDomainEntityList()
return response.body()!!.musicFolders.toDomainEntityList(activeServerId)
}
/**
@ -91,7 +91,10 @@ open class RESTMusicService(
): List<Index> {
val response = API.getIndexes(musicFolderId, null).execute().throwOnFailure()
return response.body()!!.indexes.toIndexList(musicFolderId)
return response.body()!!.indexes.toIndexList(
ActiveServerProvider.getActiveServerId(),
musicFolderId
)
}
@Throws(Exception::class)
@ -100,7 +103,7 @@ open class RESTMusicService(
): List<Artist> {
val response = API.getArtists(null).execute().throwOnFailure()
return response.body()!!.indexes.toArtistList()
return response.body()!!.indexes.toArtistList(activeServerId)
}
@Throws(Exception::class)
@ -137,7 +140,7 @@ open class RESTMusicService(
): MusicDirectory {
val response = API.getMusicDirectory(id).execute().throwOnFailure()
return response.body()!!.musicDirectory.toDomainEntity()
return response.body()!!.musicDirectory.toDomainEntity(activeServerId)
}
@Throws(Exception::class)
@ -148,7 +151,7 @@ open class RESTMusicService(
): List<Album> {
val response = API.getArtist(id).execute().throwOnFailure()
return response.body()!!.artist.toDomainEntityList()
return response.body()!!.artist.toDomainEntityList(activeServerId)
}
@Throws(Exception::class)
@ -159,7 +162,7 @@ open class RESTMusicService(
): MusicDirectory {
val response = API.getAlbum(id).execute().throwOnFailure()
return response.body()!!.album.toMusicDirectoryDomainEntity()
return response.body()!!.album.toMusicDirectoryDomainEntity(activeServerId)
}
@Throws(Exception::class)
@ -189,7 +192,7 @@ open class RESTMusicService(
API.search(null, null, null, criteria.query, criteria.songCount, null, null)
.execute().throwOnFailure()
return response.body()!!.searchResult.toDomainEntity()
return response.body()!!.searchResult.toDomainEntity(activeServerId)
}
/**
@ -205,7 +208,7 @@ open class RESTMusicService(
criteria.songCount, null
).execute().throwOnFailure()
return response.body()!!.searchResult.toDomainEntity()
return response.body()!!.searchResult.toDomainEntity(activeServerId)
}
@Throws(Exception::class)
@ -218,7 +221,7 @@ open class RESTMusicService(
criteria.songCount, null
).execute().throwOnFailure()
return response.body()!!.searchResult.toDomainEntity()
return response.body()!!.searchResult.toDomainEntity(activeServerId)
}
@Throws(Exception::class)
@ -228,7 +231,7 @@ open class RESTMusicService(
): MusicDirectory {
val response = API.getPlaylist(id).execute().throwOnFailure()
val playlist = response.body()!!.playlist.toMusicDirectoryDomainEntity()
val playlist = response.body()!!.playlist.toMusicDirectoryDomainEntity(activeServerId)
savePlaylist(name, playlist)
return playlist
@ -319,7 +322,7 @@ open class RESTMusicService(
"skipped" != podcastEntry.status &&
"error" != podcastEntry.status
) {
val entry = podcastEntry.toTrackEntity()
val entry = podcastEntry.toTrackEntity(activeServerId)
entry.track = null
musicDirectory.add(entry)
}
@ -363,7 +366,7 @@ open class RESTMusicService(
musicFolderId
).execute().throwOnFailure()
return response.body()!!.albumList.toDomainEntityList()
return response.body()!!.albumList.toDomainEntityList(activeServerId)
}
@Throws(Exception::class)
@ -383,7 +386,7 @@ open class RESTMusicService(
musicFolderId
).execute().throwOnFailure()
return response.body()!!.albumList.toDomainEntityList()
return response.body()!!.albumList.toDomainEntityList(activeServerId)
}
@Throws(Exception::class)
@ -399,7 +402,7 @@ open class RESTMusicService(
).execute().throwOnFailure()
val result = MusicDirectory()
result.addAll(response.body()!!.songsList.toDomainEntityList())
result.addAll(response.body()!!.songsList.toDomainEntityList(activeServerId))
return result
}
@ -408,14 +411,14 @@ open class RESTMusicService(
override fun getStarred(): SearchResult {
val response = API.getStarred(null).execute().throwOnFailure()
return response.body()!!.starred.toDomainEntity()
return response.body()!!.starred.toDomainEntity(activeServerId)
}
@Throws(Exception::class)
override fun getStarred2(): SearchResult {
val response = API.getStarred2(null).execute().throwOnFailure()
return response.body()!!.starred2.toDomainEntity()
return response.body()!!.starred2.toDomainEntity(activeServerId)
}
@Throws(Exception::class)
@ -546,7 +549,7 @@ open class RESTMusicService(
): List<Share> {
val response = API.getShares().execute().throwOnFailure()
return response.body()!!.shares.toDomainEntitiesList()
return response.body()!!.shares.toDomainEntitiesList(activeServerId)
}
@Throws(Exception::class)
@ -567,7 +570,7 @@ open class RESTMusicService(
val response = API.getSongsByGenre(genre, count, offset, null).execute().throwOnFailure()
val result = MusicDirectory()
result.addAll(response.body()!!.songsList.toDomainEntityList())
result.addAll(response.body()!!.songsList.toDomainEntityList(activeServerId))
return result
}
@ -601,7 +604,7 @@ open class RESTMusicService(
override fun getBookmarks(): List<Bookmark> {
val response = API.getBookmarks().execute().throwOnFailure()
return response.body()!!.bookmarkList.toDomainEntitiesList()
return response.body()!!.bookmarkList.toDomainEntitiesList(activeServerId)
}
@Throws(Exception::class)
@ -626,7 +629,7 @@ open class RESTMusicService(
val response = API.getVideos().execute().throwOnFailure()
val musicDirectory = MusicDirectory()
musicDirectory.addAll(response.body()!!.videosList.toDomainEntityList())
musicDirectory.addAll(response.body()!!.videosList.toDomainEntityList(activeServerId))
return musicDirectory
}
@ -639,7 +642,7 @@ open class RESTMusicService(
): List<Share> {
val response = API.createShare(ids, description, expires).execute().throwOnFailure()
return response.body()!!.shares.toDomainEntitiesList()
return response.body()!!.shares.toDomainEntitiesList(activeServerId)
}
@Throws(Exception::class)
@ -663,6 +666,9 @@ open class RESTMusicService(
API.updateShare(id, description, expiresValue).execute().throwOnFailure()
}
private val activeServerId: Int
get() = ActiveServerProvider.getActiveServerId()
init {
// The client will notice if the minimum supported API version has changed
// By registering a callback we ensure this info is saved in the database as well

View File

@ -7,11 +7,14 @@ import org.amshove.kluent.`should be equal to`
import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.Album
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import org.moire.ultrasonic.data.ActiveServerProvider
/**
* Unit test for extension functions in [APIAlbumConverter.kt] file.
*/
class APIAlbumConverterTest {
private val serverId = -1
@Test
fun `Should convert Album to domain entity`() {
val entity = Album(
@ -20,7 +23,7 @@ class APIAlbumConverterTest {
created = Calendar.getInstance(), year = 2017, genre = "some-genre"
)
val convertedEntity = entity.toDomainEntity()
val convertedEntity = entity.toDomainEntity(serverId)
with(convertedEntity) {
id `should be equal to` entity.id
@ -46,12 +49,12 @@ class APIAlbumConverterTest {
songList = listOf(MusicDirectoryChild())
)
val convertedEntity = entity.toMusicDirectoryDomainEntity()
val convertedEntity = entity.toMusicDirectoryDomainEntity(serverId)
with(convertedEntity) {
name `should be equal to` null
size `should be equal to` entity.songList.size
this[0] `should be equal to` entity.songList[0].toTrackEntity()
this[0] `should be equal to` entity.songList[0].toTrackEntity(serverId)
}
}
@ -59,12 +62,12 @@ class APIAlbumConverterTest {
fun `Should convert list of Album entities to domain list entities`() {
val entityList = listOf(Album(id = "455"), Album(id = "1"), Album(id = "1000"))
val convertedList = entityList.toDomainEntityList()
val convertedList = entityList.toDomainEntityList(ActiveServerProvider.getActiveServerId())
with(convertedList) {
size `should be equal to` entityList.size
forEachIndexed { index, entry ->
entry `should be equal to` entityList[index].toDomainEntity()
entry `should be equal to` entityList[index].toDomainEntity(serverId)
}
}
}

View File

@ -11,12 +11,12 @@ import org.moire.ultrasonic.api.subsonic.models.Artist
/**
* Unit test for extension functions in APIArtistConverter.kt file.
*/
class APIArtistConverterTest {
class APIArtistConverterTest : BaseTest() {
@Test
fun `Should convert artist entity`() {
val entity = Artist(id = "10", name = "artist-name", starred = Calendar.getInstance())
val convertedEntity = entity.toDomainEntity()
val convertedEntity = entity.toDomainEntity(serverId)
with(convertedEntity) {
id `should be equal to` entity.id
@ -38,12 +38,12 @@ class APIArtistConverterTest {
)
)
val convertedEntity = entity.toMusicDirectoryDomainEntity()
val convertedEntity = entity.toMusicDirectoryDomainEntity(serverId)
with(convertedEntity) {
name `should be equal to` entity.name
getChildren() `should be equal to` entity.albumsList
.map { it.toDomainEntity() }.toMutableList()
.map { it.toDomainEntity(serverId) }.toMutableList()
}
}
}

View File

@ -11,7 +11,8 @@ import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
/**
* Unit test for function that converts [Bookmark] api entity to domain.
*/
class APIBookmarkConverterTest {
class APIBookmarkConverterTest : BaseTest() {
@Test
fun `Should convert to domain entity`() {
val entity = Bookmark(
@ -19,7 +20,7 @@ class APIBookmarkConverterTest {
Calendar.getInstance(), MusicDirectoryChild(id = "12333")
)
val domainEntity = entity.toDomainEntity()
val domainEntity = entity.toDomainEntity(serverId)
with(domainEntity) {
position `should be equal to` entity.position.toInt()
@ -27,7 +28,7 @@ class APIBookmarkConverterTest {
comment `should be equal to` entity.comment
created `should be equal to` entity.created?.time
changed `should be equal to` entity.changed?.time
track `should be equal to` entity.entry.toTrackEntity()
track `should be equal to` entity.entry.toTrackEntity(serverId)
}
}
@ -35,11 +36,11 @@ class APIBookmarkConverterTest {
fun `Should convert list of entities to domain entities`() {
val entitiesList = listOf(Bookmark(443L), Bookmark(444L))
val domainEntitiesList = entitiesList.toDomainEntitiesList()
val domainEntitiesList = entitiesList.toDomainEntitiesList(serverId)
domainEntitiesList.size `should be equal to` entitiesList.size
domainEntitiesList.forEachIndexed({ index, bookmark ->
bookmark `should be equal to` entitiesList[index].toDomainEntity()
})
domainEntitiesList.forEachIndexed { index, bookmark ->
bookmark `should be equal to` entitiesList[index].toDomainEntity(serverId)
}
}
}

View File

@ -7,11 +7,12 @@ import org.amshove.kluent.`should be equal to`
import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.MusicDirectory
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import org.moire.ultrasonic.data.ActiveServerProvider
/**
* Unit test for extension functions in APIMusicDirectoryConverter.kt file.
*/
class APIMusicDirectoryConverterTest {
class APIMusicDirectoryConverterTest : BaseTest() {
@Test
fun `Should convert MusicDirectory entity`() {
val entity = MusicDirectory(
@ -20,13 +21,13 @@ class APIMusicDirectoryConverterTest {
childList = listOf(MusicDirectoryChild("1"), MusicDirectoryChild("2"))
)
val convertedEntity = entity.toDomainEntity()
val convertedEntity = entity.toDomainEntity(ActiveServerProvider.getActiveServerId())
with(convertedEntity) {
name `should be equal to` entity.name
size `should be equal to` entity.childList.size
getChildren() `should be equal to` entity.childList
.map { it.toTrackEntity() }.toMutableList()
.map { it.toTrackEntity(serverId) }.toMutableList()
}
}
@ -44,7 +45,7 @@ class APIMusicDirectoryConverterTest {
starred = Calendar.getInstance(), userRating = 3, averageRating = 2.99F
)
val convertedEntity = entity.toTrackEntity()
val convertedEntity = entity.toTrackEntity(serverId)
with(convertedEntity) {
id `should be equal to` entity.id
@ -84,7 +85,7 @@ class APIMusicDirectoryConverterTest {
artist = "some-artist", publishDate = Calendar.getInstance()
)
val convertedEntity = entity.toTrackEntity()
val convertedEntity = entity.toTrackEntity(serverId)
with(convertedEntity) {
id `should be equal to` entity.streamId
@ -96,11 +97,11 @@ class APIMusicDirectoryConverterTest {
fun `Should convert list of MusicDirectoryChild to domain entity list`() {
val entitiesList = listOf(MusicDirectoryChild(id = "45"), MusicDirectoryChild(id = "34"))
val domainList = entitiesList.toDomainEntityList()
val domainList = entitiesList.toDomainEntityList(serverId)
domainList.size `should be equal to` entitiesList.size
domainList.forEachIndexed { index, entry ->
entry `should be equal to` entitiesList[index].toTrackEntity()
entry `should be equal to` entitiesList[index].toTrackEntity(serverId)
}
}
}

View File

@ -9,12 +9,12 @@ import org.moire.ultrasonic.api.subsonic.models.MusicFolder
/**
* Unit test for extension functions in file APIMusicFolderConverter.kt.
*/
class APIMusicFolderConverterTest {
class APIMusicFolderConverterTest : BaseTest() {
@Test
fun `Should convert MusicFolder entity`() {
val entity = MusicFolder(id = "10", name = "some-name")
val convertedEntity = entity.toDomainEntity()
val convertedEntity = entity.toDomainEntity(serverId)
convertedEntity.name `should be equal to` entity.name
convertedEntity.id `should be equal to` entity.id
@ -27,7 +27,7 @@ class APIMusicFolderConverterTest {
MusicFolder(id = "4", name = "some-name-4")
)
val convertedList = entityList.toDomainEntityList()
val convertedList = entityList.toDomainEntityList(serverId)
with(convertedList) {
size `should be equal to` entityList.size

View File

@ -7,11 +7,12 @@ import org.amshove.kluent.`should be equal to`
import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import org.moire.ultrasonic.api.subsonic.models.Playlist
import org.moire.ultrasonic.data.ActiveServerProvider
/**
* Unit test for extension functions that converts api playlist entity to domain.
*/
class APIPlaylistConverterTest {
class APIPlaylistConverterTest : BaseTest() {
@Test
fun `Should convert Playlist to MusicDirectory domain entity`() {
val entity = Playlist(
@ -22,13 +23,13 @@ class APIPlaylistConverterTest {
)
)
val convertedEntity = entity.toMusicDirectoryDomainEntity()
val convertedEntity = entity.toMusicDirectoryDomainEntity(ActiveServerProvider.getActiveServerId())
with(convertedEntity) {
name `should be equal to` entity.name
size `should be equal to` entity.entriesList.size
this[0] `should be equal to` entity.entriesList[0].toTrackEntity()
this[1] `should be equal to` entity.entriesList[1].toTrackEntity()
this[0] `should be equal to` entity.entriesList[0].toTrackEntity(serverId)
this[1] `should be equal to` entity.entriesList[1].toTrackEntity(serverId)
}
}

View File

@ -11,11 +11,12 @@ import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
import org.moire.ultrasonic.api.subsonic.models.SearchResult
import org.moire.ultrasonic.api.subsonic.models.SearchThreeResult
import org.moire.ultrasonic.api.subsonic.models.SearchTwoResult
import org.moire.ultrasonic.data.ActiveServerProvider
/**
* Unit test for extension function in APISearchConverter.kt file.
*/
class APISearchConverterTest {
class APISearchConverterTest : BaseTest() {
@Test
fun `Should convert SearchResult to domain entity`() {
val entity = SearchResult(
@ -26,7 +27,7 @@ class APISearchConverterTest {
)
)
val convertedEntity = entity.toDomainEntity()
val convertedEntity = entity.toDomainEntity(serverId)
with(convertedEntity) {
albums `should not be equal to` null
@ -34,7 +35,7 @@ class APISearchConverterTest {
artists `should not be equal to` null
artists.size `should be equal to` 0
songs.size `should be equal to` entity.matchList.size
songs[0] `should be equal to` entity.matchList[0].toTrackEntity()
songs[0] `should be equal to` entity.matchList[0].toTrackEntity(serverId)
}
}
@ -46,15 +47,15 @@ class APISearchConverterTest {
listOf(MusicDirectoryChild(id = "9118", parent = "112"))
)
val convertedEntity = entity.toDomainEntity()
val convertedEntity = entity.toDomainEntity(ActiveServerProvider.getActiveServerId())
with(convertedEntity) {
artists.size `should be equal to` entity.artistList.size
artists[0] `should be equal to` entity.artistList[0].toIndexEntity()
artists[0] `should be equal to` entity.artistList[0].toIndexEntity(serverId)
albums.size `should be equal to` entity.albumList.size
albums[0] `should be equal to` entity.albumList[0].toDomainEntity()
albums[0] `should be equal to` entity.albumList[0].toDomainEntity(serverId)
songs.size `should be equal to` entity.songList.size
songs[0] `should be equal to` entity.songList[0].toTrackEntity()
songs[0] `should be equal to` entity.songList[0].toTrackEntity(serverId)
}
}
@ -66,15 +67,15 @@ class APISearchConverterTest {
songList = listOf(MusicDirectoryChild(id = "7123", title = "song1"))
)
val convertedEntity = entity.toDomainEntity()
val convertedEntity = entity.toDomainEntity(serverId)
with(convertedEntity) {
artists.size `should be equal to` entity.artistList.size
artists[0] `should be equal to` entity.artistList[0].toDomainEntity()
artists[0] `should be equal to` entity.artistList[0].toDomainEntity(serverId)
albums.size `should be equal to` entity.albumList.size
albums[0] `should be equal to` entity.albumList[0].toDomainEntity()
albums[0] `should be equal to` entity.albumList[0].toDomainEntity(serverId)
songs.size `should be equal to` entity.songList.size
songs[0] `should be equal to` entity.songList[0].toTrackEntity()
songs[0] `should be equal to` entity.songList[0].toTrackEntity(serverId)
}
}
}

View File

@ -0,0 +1,12 @@
/*
* BaseTest.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.domain
open class BaseTest {
internal val serverId = -1
}