Skip to content

Commit

Permalink
Implement non-gms upload (#43)
Browse files Browse the repository at this point in the history
* Storage sdk - Implement non-gms upload and return null in gms(implement in other task).

* Storage sdk: Add constants and missing space. Don't force unwrap nullable values.

* Storage sdk - Change to private and refactor JSON_MIME_TYPE constant value

* Solved comments

* Solve conflicts

---------

Co-authored-by: Hector A. Narvaez <hector.narvaez@encora.com>
  • Loading branch information
hans-hamel and HectorNarvaez committed Jun 21, 2023
1 parent 9e89281 commit 3fe751d
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.omh.android.storage.api.drive.gms.data.repository

import com.omh.android.storage.api.data.source.OmhFileRemoteDataSource
import com.omh.android.storage.api.domain.repository.OmhFileRepository
import java.io.File

internal class GmsFileRepositoryImpl(private val dataSource: OmhFileRemoteDataSource) : OmhFileRepository {

Expand All @@ -12,11 +13,12 @@ internal class GmsFileRepositoryImpl(private val dataSource: OmhFileRemoteDataSo

override fun deleteFile(fileId: String) = dataSource.deleteFile(fileId)

override fun uploadFile(localFileToUpload: File, fileName: String, parentId: String?) =
dataSource.uploadFile(localFileToUpload, fileName, parentId)

override fun open() = Unit

override fun update() = Unit

override fun upload() = Unit

override fun download() = Unit
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
package com.omh.android.storage.api.drive.gms.data.source

import com.google.api.services.drive.model.File
import com.google.api.services.drive.model.FileList
import com.omh.android.storage.api.data.source.OmhFileRemoteDataSource
import com.omh.android.storage.api.domain.model.OmhFile
import com.omh.android.storage.api.drive.gms.data.GoogleDriveApiService
import com.omh.android.storage.api.drive.gms.data.source.mapper.toOmhFile
import java.io.File
import com.google.api.services.drive.model.File as GoogleApiFile

internal class GmsFileRemoteDataSourceImpl(private val apiService: GoogleDriveApiService) :
OmhFileRemoteDataSource {

override fun getFilesList(parentId: String): List<OmhFile> {
val googleJsonFileList: FileList = apiService.getFilesList(parentId).execute()
val googleFileList: List<File> = googleJsonFileList.files.toList()
val googleFileList: List<GoogleApiFile> = googleJsonFileList.files.toList()
return googleFileList.mapNotNull { googleFile -> googleFile.toOmhFile() }
}

override fun createFile(name: String, mimeType: String, parentId: String?): OmhFile? {
val fileToBeCreated = File().apply {
val fileToBeCreated = GoogleApiFile().apply {
this.name = name
this.mimeType = mimeType
if (parentId != null) {
this.parents = listOf(parentId)
}
}

val responseFile: File = apiService.createFile(fileToBeCreated).execute()
val responseFile: GoogleApiFile = apiService.createFile(fileToBeCreated).execute()

return responseFile.toOmhFile()
}
Expand All @@ -39,4 +40,6 @@ internal class GmsFileRemoteDataSourceImpl(private val apiService: GoogleDriveAp
false
}
}

override fun uploadFile(localFileToUpload: File, fileName: String, parentId: String?) = null
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.omh.android.auth.api.OmhCredentials
import com.omh.android.storage.api.drive.nongms.BuildConfig
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.jackson.JacksonConverterFactory

Expand Down Expand Up @@ -43,27 +42,14 @@ internal class GoogleRetrofitImpl(private val omhCredentials: OmhCredentials) {
}

private fun createOkHttpClient(): OkHttpClient {
val loggingInterceptor = setupLoggingInterceptor()

return OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.addInterceptor { chain ->
val request = setupRequestInterceptor(chain)
chain.proceed(request)
}
.build()
}

private fun setupLoggingInterceptor() = HttpLoggingInterceptor().apply {
setLevel(
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor.Level.BODY
} else {
HttpLoggingInterceptor.Level.NONE
}
)
}

private fun setupRequestInterceptor(chain: Interceptor.Chain) = chain
.request()
.newBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ package com.omh.android.storage.api.drive.nongms.data
import com.omh.android.storage.api.drive.nongms.data.source.body.CreateFileRequestBody
import com.omh.android.storage.api.drive.nongms.data.source.response.FileListRemoteResponse
import com.omh.android.storage.api.drive.nongms.data.source.response.FileRemoteResponse
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
import retrofit2.http.Path
import retrofit2.http.Query

internal interface GoogleStorageApiService {

companion object {
private const val FILES_PARTICLE = "drive/v3/files"
private const val UPLOAD_FILES_PARTICLE = "upload/drive/v3/files"

private const val QUERY_Q = "q"
private const val QUERY_FIELDS = "fields"
Expand All @@ -28,6 +33,7 @@ internal interface GoogleStorageApiService {
private const val FIELDS_VALUE = "files($QUERY_REQUESTED_FIELDS)"

private const val FILE_ID = "fileId"
private const val META_DATA = "metadata"
}

@GET(FILES_PARTICLE)
Expand All @@ -46,4 +52,11 @@ internal interface GoogleStorageApiService {
fun deleteFile(
@Path(FILE_ID) fileId: String
): Call<ResponseBody>

@Multipart
@POST(UPLOAD_FILES_PARTICLE)
fun uploadFile(
@Part(META_DATA) metadata: RequestBody,
@Part filePart: MultipartBody.Part
): Call<FileRemoteResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.omh.android.storage.api.drive.nongms.data.repository

import com.omh.android.storage.api.data.source.OmhFileRemoteDataSource
import com.omh.android.storage.api.domain.repository.OmhFileRepository
import java.io.File

internal class NonGmsFileRepositoryImpl(
private val dataSource: OmhFileRemoteDataSource
Expand All @@ -15,11 +16,12 @@ internal class NonGmsFileRepositoryImpl(

override fun deleteFile(fileId: String) = dataSource.deleteFile(fileId)

override fun uploadFile(localFileToUpload: File, fileName: String, parentId: String?) =
dataSource.uploadFile(localFileToUpload, fileName, parentId)

override fun open() = Unit

override fun update() = Unit

override fun upload() = Unit

override fun download() = Unit
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
package com.omh.android.storage.api.drive.nongms.data.source

import android.webkit.MimeTypeMap
import com.omh.android.storage.api.data.source.OmhFileRemoteDataSource
import com.omh.android.storage.api.domain.model.OmhFile
import com.omh.android.storage.api.drive.nongms.data.GoogleRetrofitImpl
import com.omh.android.storage.api.drive.nongms.data.GoogleStorageApiService
import com.omh.android.storage.api.drive.nongms.data.source.body.CreateFileRequestBody
import com.omh.android.storage.api.drive.nongms.data.source.mapper.toFile
import com.omh.android.storage.api.drive.nongms.data.source.mapper.toFileList
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONArray
import org.json.JSONObject
import java.io.File

internal class NonGmsFileRemoteDataSourceImpl(private val retrofitImpl: GoogleRetrofitImpl) :
OmhFileRemoteDataSource {

companion object {
private const val FILE_NAME_KEY = "name"
private const val FILE_PARENTS_KEY = "parents"
private const val ANY_MIME_TYPE = "*/*"

private val JSON_MIME_TYPE = "application/json".toMediaTypeOrNull()
}

override fun getFilesList(parentId: String): List<OmhFile> {
val response = retrofitImpl
.getGoogleStorageApiService()
Expand Down Expand Up @@ -55,4 +71,43 @@ internal class NonGmsFileRemoteDataSourceImpl(private val retrofitImpl: GoogleRe

return response.isSuccessful
}

override fun uploadFile(
localFileToUpload: File,
fileName: String,
parentId: String?
): OmhFile? {
val stringMimeType = MimeTypeMap
.getSingleton()
.getMimeTypeFromExtension(localFileToUpload.extension)
?: ANY_MIME_TYPE

val mimeType = stringMimeType.toMediaTypeOrNull()
val requestFile = localFileToUpload.asRequestBody(mimeType)
val parentsList = if (parentId.isNullOrBlank()) {
emptyList()
} else {
listOf(parentId)
}

val parentsListAsJson = JSONArray(parentsList)
val jsonMetaData = JSONObject().apply {
put(FILE_NAME_KEY, fileName)
put(FILE_PARENTS_KEY, parentsListAsJson)
}

val jsonRequestBody = jsonMetaData.toString().toRequestBody(JSON_MIME_TYPE)
val filePart = MultipartBody.Part.createFormData(FILE_NAME_KEY, fileName, requestFile)

val response = retrofitImpl
.getGoogleStorageApiService()
.uploadFile(jsonRequestBody, filePart)
.execute()

return if (response.isSuccessful) {
response.body()?.toFile()
} else {
null
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import com.omh.android.storage.api.domain.usecase.GetFilesListUseCase
import com.omh.android.storage.api.domain.usecase.GetFilesListUseCaseParams
import com.omh.android.storage.api.domain.usecase.GetFilesListUseCaseResult
import com.omh.android.storage.api.domain.usecase.OmhResult
import com.omh.android.storage.api.domain.usecase.UploadFileUseCase
import com.omh.android.storage.api.domain.usecase.UploadFileUseCaseParams
import com.omh.android.storage.api.domain.usecase.UploadFileUseCaseResult
import java.io.File

abstract class OmhStorageClient protected constructor(
protected val authClient: OmhAuthClient
Expand Down Expand Up @@ -56,4 +60,17 @@ abstract class OmhStorageClient protected constructor(
result
}
}

fun uploadFile(
localFileToUpload: File,
fileName: String,
parentId: String?
): OmhTask<UploadFileUseCaseResult> {
val uploadFileUseCase = UploadFileUseCase(getRepository())
return OmhStorageTaskImpl {
val parameters = UploadFileUseCaseParams(localFileToUpload, fileName, parentId)
val result = uploadFileUseCase(parameters)
result
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.omh.android.storage.api.data.source

import com.omh.android.storage.api.domain.model.OmhFile
import java.io.File

interface OmhFileRemoteDataSource {

Expand All @@ -12,4 +13,6 @@ interface OmhFileRemoteDataSource {
* @return true if the file was deleted, false otherwise
*/
fun deleteFile(fileId: String): Boolean

fun uploadFile(localFileToUpload: File, fileName: String, parentId: String?): OmhFile?
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.omh.android.storage.api.domain.repository

import com.omh.android.storage.api.domain.model.OmhFile
import java.io.File

interface OmhFileRepository {

Expand All @@ -10,11 +11,11 @@ interface OmhFileRepository {

fun deleteFile(fileId: String): Boolean

fun uploadFile(localFileToUpload: File, fileName: String, parentId: String?): OmhFile?

fun open()

fun update()

fun upload()

fun download()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.omh.android.storage.api.domain.usecase

import com.omh.android.storage.api.domain.model.OmhFile
import com.omh.android.storage.api.domain.repository.OmhFileRepository
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import java.io.File

class UploadFileUseCase(
private val repository: OmhFileRepository,
dispatcher: CoroutineDispatcher = Dispatchers.Default
) : OmhSuspendUseCase<UploadFileUseCaseParams, UploadFileUseCaseResult>(dispatcher) {

override suspend fun execute(parameters: UploadFileUseCaseParams): UploadFileUseCaseResult {
return UploadFileUseCaseResult(
repository.uploadFile(parameters.localFileToUpload, parameters.fileName, parameters.parentId)
)
}
}

data class UploadFileUseCaseParams(val localFileToUpload: File, val fileName: String, val parentId: String?)

data class UploadFileUseCaseResult(val file: OmhFile?)

0 comments on commit 3fe751d

Please sign in to comment.