From 8dc9534327b7a9ebcf6d1b84a37050d723e06cfa Mon Sep 17 00:00:00 2001
From: Yahor Berdnikau <egorr.berd@gmail.com>
Date: Sat, 23 Jun 2018 22:30:11 +0200
Subject: [PATCH] Move api client configuration to separate data class.

Signed-off-by: Yahor Berdnikau <egorr.berd@gmail.com>
---
 .../api/subsonic/GetStreamUrlTest.kt          | 10 ++++--
 .../api/subsonic/SubsonicAPIClientTest.kt     | 11 ++++--
 .../api/subsonic/SubsonicApiPasswordTest.kt   | 10 +++---
 .../api/subsonic/SubsonicApiSSLTest.kt        | 14 ++++++--
 .../api/subsonic/SubsonicAPIClient.kt         | 35 ++++++++-----------
 .../subsonic/SubsonicClientConfiguration.kt   | 15 ++++++++
 .../moire/ultrasonic/di/MusicServiceModule.kt |  7 ++--
 7 files changed, 69 insertions(+), 33 deletions(-)
 create mode 100644 subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicClientConfiguration.kt

diff --git a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/GetStreamUrlTest.kt b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/GetStreamUrlTest.kt
index 063a5cf7..2b828a1a 100644
--- a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/GetStreamUrlTest.kt
+++ b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/GetStreamUrlTest.kt
@@ -21,8 +21,14 @@ class GetStreamUrlTest {
 
     @Before
     fun setUp() {
-        client = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
-                USERNAME, PASSWORD, V1_6_0, CLIENT_ID)
+        val config = SubsonicClientConfiguration(
+            mockWebServerRule.mockWebServer.url("/").toString(),
+            USERNAME,
+            PASSWORD,
+            V1_6_0,
+            CLIENT_ID
+        )
+        client = SubsonicAPIClient(config)
         val baseExpectedUrl = mockWebServerRule.mockWebServer.url("").toString()
         expectedUrl = "$baseExpectedUrl/rest/stream.view?id=$id&u=$USERNAME" +
                 "&c=$CLIENT_ID&f=json&v=${V1_6_0.restApiVersion}&p=enc:${PASSWORD.toHexBytes()}"
diff --git a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClientTest.kt b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClientTest.kt
index 6d4dfffd..d82c34c2 100644
--- a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClientTest.kt
+++ b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClientTest.kt
@@ -10,11 +10,18 @@ import org.moire.ultrasonic.api.subsonic.rules.MockWebServerRule
 abstract class SubsonicAPIClientTest {
     @JvmField @Rule val mockWebServerRule = MockWebServerRule()
 
+    protected lateinit var config: SubsonicClientConfiguration
     protected lateinit var client: SubsonicAPIClient
 
     @Before
     fun setUp() {
-        client = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
-                USERNAME, PASSWORD, CLIENT_VERSION, CLIENT_ID)
+        config = SubsonicClientConfiguration(
+            mockWebServerRule.mockWebServer.url("/").toString(),
+            USERNAME,
+            PASSWORD,
+            CLIENT_VERSION,
+            CLIENT_ID
+        )
+        client = SubsonicAPIClient(config)
     }
 }
diff --git a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiPasswordTest.kt b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiPasswordTest.kt
index 1a10e6cb..536cb8a7 100644
--- a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiPasswordTest.kt
+++ b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiPasswordTest.kt
@@ -10,8 +10,9 @@ import org.junit.Test
 class SubsonicApiPasswordTest : SubsonicAPIClientTest() {
     @Test
     fun `Should pass PasswordMD5Interceptor in query params for api version 1 13 0`() {
-        val clientV12 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
-                USERNAME, PASSWORD, SubsonicAPIVersions.V1_14_0, CLIENT_ID)
+        val clientV12 = SubsonicAPIClient(
+            config.copy(minimalProtocolVersion = SubsonicAPIVersions.V1_14_0)
+        )
         mockWebServerRule.enqueueResponse("ping_ok.json")
 
         clientV12.api.ping().execute()
@@ -25,8 +26,9 @@ class SubsonicApiPasswordTest : SubsonicAPIClientTest() {
 
     @Test
     fun `Should pass PasswordHexInterceptor in query params for api version 1 12 0`() {
-        val clientV11 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
-                USERNAME, PASSWORD, SubsonicAPIVersions.V1_12_0, CLIENT_ID)
+        val clientV11 = SubsonicAPIClient(
+            config.copy(minimalProtocolVersion = SubsonicAPIVersions.V1_12_0)
+        )
         mockWebServerRule.enqueueResponse("ping_ok.json")
 
         clientV11.api.ping().execute()
diff --git a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiSSLTest.kt b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiSSLTest.kt
index fb43dbc1..89f8f21d 100644
--- a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiSSLTest.kt
+++ b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiSSLTest.kt
@@ -90,7 +90,15 @@ class SubsonicApiSSLTest {
         assertResponseSuccessful(response)
     }
 
-    private fun createSubsonicClient(allowSelfSignedCertificate: Boolean) = SubsonicAPIClient(
-            "https://$HOST:$PORT/", USERNAME, PASSWORD, CLIENT_VERSION, CLIENT_ID,
-            allowSelfSignedCertificate = allowSelfSignedCertificate)
+    private fun createSubsonicClient(allowSelfSignedCertificate: Boolean): SubsonicAPIClient {
+        val config = SubsonicClientConfiguration(
+            "https://$HOST:$PORT/",
+            USERNAME,
+            PASSWORD,
+            CLIENT_VERSION,
+            CLIENT_ID,
+            allowSelfSignedCertificate = allowSelfSignedCertificate
+        )
+        return SubsonicAPIClient(config)
+    }
 }
diff --git a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClient.kt b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClient.kt
index 577e55d2..6f407576 100644
--- a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClient.kt
+++ b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClient.kt
@@ -36,29 +36,23 @@ private const val READ_TIMEOUT = 60_000L
  * @author Yahor Berdnikau
  */
 class SubsonicAPIClient(
-    baseUrl: String,
-    username: String,
-    password: String,
-    minimalProtocolVersion: SubsonicAPIVersions,
-    clientID: String,
-    allowSelfSignedCertificate: Boolean = false,
-    enableLdapUserSupport: Boolean = false,
-    debug: Boolean = false
+    config: SubsonicClientConfiguration
 ) {
-    private val versionInterceptor = VersionInterceptor(minimalProtocolVersion) {
+    private val versionInterceptor = VersionInterceptor(config.minimalProtocolVersion) {
         protocolVersion = it
     }
 
     private val proxyPasswordInterceptor = ProxyPasswordInterceptor(
-            minimalProtocolVersion,
-            PasswordHexInterceptor(password),
-            PasswordMD5Interceptor(password),
-            enableLdapUserSupport)
+            config.minimalProtocolVersion,
+            PasswordHexInterceptor(config.password),
+            PasswordMD5Interceptor(config.password),
+            config.enableLdapUserSupport
+    )
 
     /**
      * Get currently used protocol version.
      */
-    var protocolVersion = minimalProtocolVersion
+    var protocolVersion = config.minimalProtocolVersion
         private set(value) {
             field = value
             proxyPasswordInterceptor.apiVersion = field
@@ -67,13 +61,13 @@ class SubsonicAPIClient(
 
     private val okHttpClient = OkHttpClient.Builder()
             .readTimeout(READ_TIMEOUT, MILLISECONDS)
-            .apply { if (allowSelfSignedCertificate) allowSelfSignedCertificates() }
+            .apply { if (config.allowSelfSignedCertificate) allowSelfSignedCertificates() }
             .addInterceptor { chain ->
                 // Adds default request params
                 val originalRequest = chain.request()
                 val newUrl = originalRequest.url().newBuilder()
-                        .addQueryParameter("u", username)
-                        .addQueryParameter("c", clientID)
+                        .addQueryParameter("u", config.username)
+                        .addQueryParameter("c", config.clientID)
                         .addQueryParameter("f", "json")
                         .build()
                 chain.proceed(originalRequest.newBuilder().url(newUrl).build())
@@ -81,7 +75,7 @@ class SubsonicAPIClient(
             .addInterceptor(versionInterceptor)
             .addInterceptor(proxyPasswordInterceptor)
             .addInterceptor(RangeHeaderInterceptor())
-            .apply { if (debug) addLogging() }
+            .apply { if (config.debug) addLogging() }
             .build()
 
     private val jacksonMapper = ObjectMapper()
@@ -90,14 +84,15 @@ class SubsonicAPIClient(
             .registerModule(KotlinModule())
 
     private val retrofit = Retrofit.Builder()
-            .baseUrl("$baseUrl/rest/")
+            .baseUrl("${config.baseUrl}/rest/")
             .client(okHttpClient)
             .addConverterFactory(JacksonConverterFactory.create(jacksonMapper))
             .build()
 
     private val wrappedApi = ApiVersionCheckWrapper(
             retrofit.create(SubsonicAPIDefinition::class.java),
-            minimalProtocolVersion)
+            config.minimalProtocolVersion
+    )
 
     val api: SubsonicAPIDefinition get() = wrappedApi
 
diff --git a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicClientConfiguration.kt b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicClientConfiguration.kt
new file mode 100644
index 00000000..732efe7a
--- /dev/null
+++ b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicClientConfiguration.kt
@@ -0,0 +1,15 @@
+package org.moire.ultrasonic.api.subsonic
+
+/**
+ * Provides configuration for [SubsonicAPIClient].
+ */
+data class SubsonicClientConfiguration(
+    val baseUrl: String,
+    val username: String,
+    val password: String,
+    val minimalProtocolVersion: SubsonicAPIVersions,
+    val clientID: String,
+    val allowSelfSignedCertificate: Boolean = false,
+    val enableLdapUserSupport: Boolean = false,
+    val debug: Boolean = false
+)
diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt
index 57fa1607..e0c110d1 100644
--- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt
+++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt
@@ -7,6 +7,7 @@ import org.koin.dsl.module.applicationContext
 import org.moire.ultrasonic.BuildConfig
 import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
 import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions
+import org.moire.ultrasonic.api.subsonic.SubsonicClientConfiguration
 import org.moire.ultrasonic.cache.PermanentFileStorage
 import org.moire.ultrasonic.service.CachedMusicService
 import org.moire.ultrasonic.service.MusicService
@@ -68,7 +69,7 @@ fun musicServiceModule(sp: SharedPreferences) = applicationContext {
                 password == null
             ) {
                 Log.i(LOG_TAG, "Server credentials is not available")
-                return@bean SubsonicAPIClient(
+                return@bean SubsonicClientConfiguration(
                     baseUrl = "http://localhost",
                     username = "",
                     password = "",
@@ -81,7 +82,7 @@ fun musicServiceModule(sp: SharedPreferences) = applicationContext {
                     debug = BuildConfig.DEBUG
                 )
             } else {
-                return@bean SubsonicAPIClient(
+                return@bean SubsonicClientConfiguration(
                     baseUrl = serverUrl,
                     username = username,
                     password = password,
@@ -96,6 +97,8 @@ fun musicServiceModule(sp: SharedPreferences) = applicationContext {
             }
         }
 
+        bean { return@bean SubsonicAPIClient(get()) }
+
         bean<MusicService>(name = ONLINE_MUSIC_SERVICE) {
             return@bean CachedMusicService(RESTMusicService(get(), get()))
         }