This repository has been archived by the owner on Oct 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(desktop): add DesktopRemoteDataSource and implementation
- Loading branch information
1 parent
dcef1e3
commit a2556f1
Showing
2 changed files
with
193 additions
and
0 deletions.
There are no files selected for viewing
54 changes: 54 additions & 0 deletions
54
...src/main/kotlin/com/intelligentbackpack/desktopdata/datasource/DesktopRemoteDataSource.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.intelligentbackpack.desktopdata.datasource | ||
|
||
import com.intelligentbackpack.accessdomain.entities.Email | ||
import com.intelligentbackpack.accessdomain.entities.User | ||
import com.intelligentbackpack.desktopdomain.entities.Book | ||
import com.intelligentbackpack.desktopdomain.entities.Desktop | ||
import com.intelligentbackpack.desktopdomain.entities.SchoolSupply | ||
import kotlinx.coroutines.flow.Flow | ||
|
||
/** | ||
* Interface for the desktop remote data source. | ||
*/ | ||
interface DesktopRemoteDataSource { | ||
/** | ||
* Gets a book by its ISBN. | ||
* | ||
* @param isbn The ISBN of the book. | ||
* @return The book if it exists. | ||
*/ | ||
fun getBook(isbn: String): Book? | ||
|
||
/** | ||
* Gets the desktop. | ||
* | ||
* @param user The user. | ||
* @return The desktop. | ||
*/ | ||
fun getDesktop(user: User): Desktop | ||
|
||
/** | ||
* Adds a school supply to the desktop. | ||
* | ||
* @param user The user. | ||
* @param schoolSupply The school supply to add. | ||
*/ | ||
fun addSchoolSupply(user: User, schoolSupply: SchoolSupply) | ||
|
||
/** | ||
* Subscribes to the backpack. | ||
* | ||
* @param email the email that subscribe to the backpack | ||
* @param backpack the backpack to subscribe | ||
* @return a [Flow] with the set of rfid of school supplies in the backpack | ||
*/ | ||
fun subscribeToBackpackChanges(email: Email, backpack: String): Flow<Result<Set<String>>> | ||
|
||
/** | ||
* Associates a backpack to a user. | ||
* | ||
* @param user the user to associate the backpack | ||
* @param hash the hash of the backpack to associate | ||
*/ | ||
fun associateBackpack(user: User, hash: String) | ||
} |
139 changes: 139 additions & 0 deletions
139
...main/kotlin/com/intelligentbackpack/desktopdata/datasource/DesktopRemoteDataSourceImpl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
package com.intelligentbackpack.desktopdata.datasource | ||
|
||
import book.communication.BuyBook | ||
import com.google.firebase.database.DataSnapshot | ||
import com.google.firebase.database.DatabaseError | ||
import com.google.firebase.database.ValueEventListener | ||
import com.google.firebase.database.ktx.database | ||
import com.google.firebase.ktx.Firebase | ||
import com.intelligentbackpack.accessdomain.entities.Email | ||
import com.intelligentbackpack.accessdomain.entities.User | ||
import com.intelligentbackpack.desktopdata.adapter.BookAdapter.fromRemoteToDomain | ||
import com.intelligentbackpack.desktopdata.adapter.SchoolSupplyAdapter.fromRemoteToDomain | ||
import com.intelligentbackpack.desktopdata.api.BackpackApi | ||
import com.intelligentbackpack.desktopdata.api.DesktopApi | ||
import com.intelligentbackpack.desktopdomain.entities.Book | ||
import com.intelligentbackpack.desktopdomain.entities.BookCopy | ||
import com.intelligentbackpack.desktopdomain.entities.Desktop | ||
import com.intelligentbackpack.desktopdomain.entities.SchoolSupply | ||
import com.intelligentbackpack.desktopdomain.policies.RFIDPolicy | ||
import com.intelligentbackpack.networkutility.DownloadException | ||
import com.intelligentbackpack.networkutility.ErrorHandler.getError | ||
import com.intelligentbackpack.networkutility.RetrofitHelper | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import kotlinx.coroutines.channels.awaitClose | ||
import kotlinx.coroutines.flow.callbackFlow | ||
import kotlinx.coroutines.runBlocking | ||
|
||
class DesktopRemoteDataSourceImpl( | ||
baseUrl: String, | ||
backpackUrl: String, | ||
realtimeUrl: String, | ||
) : DesktopRemoteDataSource { | ||
|
||
private val desktopApi = RetrofitHelper.getInstance(baseUrl).create(DesktopApi::class.java) | ||
private val backpackApi = RetrofitHelper.getInstance(backpackUrl).create(BackpackApi::class.java) | ||
private val database = Firebase.database(realtimeUrl) | ||
override fun getBook(isbn: String): Book? { | ||
val response = desktopApi.getBook(isbn).execute() | ||
if (response.isSuccessful) { | ||
return response.body()?.fromRemoteToDomain() | ||
} else { | ||
throw DownloadException(getError(response)) | ||
} | ||
} | ||
|
||
override fun getDesktop(user: User): Desktop { | ||
val response = desktopApi.getLibrary(user.email).execute() | ||
if (response.isSuccessful) { | ||
val books = response.body() | ||
?.copiesList | ||
?.mapNotNull { getBook(it.isbn) } | ||
?.toSet() | ||
?: emptySet() | ||
val copies = response.body() | ||
?.copiesList | ||
?.map { it.fromRemoteToDomain(books) } | ||
?.toSet() | ||
?: emptySet() | ||
val backpacks = database.reference | ||
.child(user.email) | ||
.get().result | ||
val hasBackpack = backpacks.key != null | ||
val supplyInBackpack = backpacks.children | ||
.asSequence() | ||
.mapNotNull { it.getValue(String::class.java) } | ||
.map { it.uppercase() } | ||
.filter { RFIDPolicy.isValid(it) } | ||
.toSet() | ||
return Desktop.create( | ||
schoolSupplies = copies, | ||
schoolSuppliesInBackpack = copies.filter { it.rfidCode in supplyInBackpack }.toSet(), | ||
backpackAssociated = hasBackpack, | ||
) | ||
} else { | ||
throw DownloadException(getError(response)) | ||
} | ||
} | ||
|
||
override fun addSchoolSupply(user: User, schoolSupply: SchoolSupply) { | ||
if (schoolSupply is BookCopy) { | ||
val copy = BuyBook.newBuilder().apply { | ||
isbn = schoolSupply.book.isbn | ||
rfid = schoolSupply.rfidCode | ||
emailCompratore = user.email | ||
}.build() | ||
val response = desktopApi.addBookCopy(copy).execute() | ||
if (!response.isSuccessful) { | ||
throw DownloadException(getError(response)) | ||
} | ||
} else { | ||
throw DownloadException("School supply not supported") | ||
} | ||
} | ||
|
||
@ExperimentalCoroutinesApi | ||
override fun subscribeToBackpackChanges(email: Email, backpack: String) = | ||
callbackFlow<Result<Set<String>>> { | ||
val postListener = object : ValueEventListener { | ||
override fun onCancelled(error: DatabaseError) { | ||
runBlocking { | ||
this@callbackFlow.send(Result.failure(error.toException())) | ||
} | ||
} | ||
|
||
override fun onDataChange(dataSnapshot: DataSnapshot) { | ||
val items = dataSnapshot.children.map { it.key } | ||
runBlocking { | ||
this@callbackFlow.send( | ||
Result.success( | ||
items | ||
.filterNotNull() | ||
.map { it.uppercase() } | ||
.filter { RFIDPolicy.isValid(it) } | ||
.toSet() | ||
) | ||
) | ||
} | ||
} | ||
} | ||
database.reference | ||
.child(email) | ||
.child(backpack) | ||
.addValueEventListener(postListener) | ||
|
||
awaitClose { | ||
database.reference | ||
.child(email) | ||
.child(backpack) | ||
.removeEventListener(postListener) | ||
} | ||
} | ||
|
||
override fun associateBackpack(user: User, hash: String) { | ||
val response = backpackApi.associateBackpack(user.email, hash).execute() | ||
if (!response.isSuccessful) { | ||
throw DownloadException(getError(response)) | ||
} | ||
} | ||
} |