HumanLearning2021/HumanLearningApp

View on GitHub
app/src/main/java/com/github/HumanLearning2021/HumanLearningApp/model/DummyDatabaseService.kt

Summary

Maintainability
A
0 mins
Test Coverage
A
97%
package com.github.HumanLearning2021.HumanLearningApp.model

import android.net.Uri
import com.google.firebase.auth.FirebaseUser
import java.util.*

/**
 * A class representing a dummy data set Interface
 * Categories are uniquely defined by their name
 */
@Suppress("OverridingDeprecatedMember")
class DummyDatabaseService internal constructor() : DatabaseService {
    private val pictures = InMemoryRepository<CategorizedPicture>()
    private val categories = InMemoryRepository<Category>()
    private val datasets = InMemoryRepository<Dataset>()
    private val representativePictures: MutableMap<String, CategorizedPicture> = mutableMapOf()
    private val users = InMemoryRepository<User>()

    private suspend fun requireCategoryPresent(category: Category) {
        categories.getById(category.id) ?: throw DatabaseService.NotFoundException(category.id)
    }

    private suspend fun requireDatasetPresent(dataset: Dataset) {
        datasets.getById(dataset.id) ?: throw DatabaseService.NotFoundException(dataset.id)
    }

    private suspend fun requirePicturePresent(picture: CategorizedPicture) {
        pictures.getById(picture.id) ?: throw DatabaseService.NotFoundException(picture.id)
    }

    override suspend fun getPicture(category: Category): CategorizedPicture? {
        requireCategoryPresent(category)

        return pictures.getIds().map { pictures.getById(it) }
            .find { it?.category?.id == category.id }
    }

    override suspend fun getPicture(pictureId: Id): CategorizedPicture? =
        pictures.getById(pictureId)

    override suspend fun getPictureIds(category: Category): List<Id> {
        requireCategoryPresent(category)
        return pictures.getIds().filter { pictures.getById(it)?.category?.id == category.id }
    }

    override suspend fun getRepresentativePicture(categoryId: Id): CategorizedPicture? {
        return representativePictures[categoryId]
    }

    override suspend fun putPicture(picture: Uri, category: Category): CategorizedPicture {
        requireCategoryPresent(category)

        val addedPicture = CategorizedPicture("", category, picture)
        val id = pictures.createWith { addedPicture.copy(id = it) }

        return addedPicture.copy(id = id)
    }

    override suspend fun getCategory(id: Id): Category? {
        return categories.getById(id)
    }

    override suspend fun putCategory(categoryName: String): Category {
        val category = Category(categoryName, categoryName)
        categories.update(categoryName, category)
        return category
    }

    override suspend fun getCategories(): Set<Category> {
        return categories.getIds().mapNotNull { categories.getById(it) }.toSet()
    }

    override suspend fun getAllPictures(category: Category): Set<CategorizedPicture> {
        requireCategoryPresent(category)

        return getPictureIds(category).mapNotNull { pictures.getById(it) }.toSet()
    }

    override suspend fun removeCategory(category: Category) {
        requireCategoryPresent(category)
        datasets.updateAll {
            it.copy(categories = it.categories - category)
        }
        categories.delete(category.id)
    }

    override suspend fun removePicture(picture: CategorizedPicture) {
        if (!pictures.delete(picture.id)) throw DatabaseService.NotFoundException(picture.id)
    }

    override suspend fun putDataset(name: String, categories: Set<Category>): Dataset {
        val dataset = Dataset(name, name, categories)
        datasets.update(name, dataset)
        return dataset
    }

    override suspend fun getDataset(id: Id): Dataset? =
        datasets.getById(id)

    override suspend fun deleteDataset(id: Id) {
        if (!datasets.delete(id)) throw DatabaseService.NotFoundException(id)
    }

    override suspend fun putRepresentativePicture(picture: Uri, category: Category) {
        requireCategoryPresent(category)
        representativePictures[category.id] =
            CategorizedPicture("${UUID.randomUUID()}", category, picture)
    }

    override suspend fun putRepresentativePicture(picture: CategorizedPicture) {
        requirePicturePresent(picture)
        putRepresentativePicture(picture.picture, picture.category)
        pictures.delete(picture.id)
    }

    override suspend fun getDatasets(): Set<Dataset> {
        return datasets.getIds().mapNotNull { datasets.getById(it) }.toSet()
    }

    override suspend fun removeCategoryFromDataset(
        dataset: Dataset,
        category: Category
    ): Dataset {
        requireDatasetPresent(dataset)
        return dataset.copy(categories = dataset.categories - category).also {
            datasets.update(it.id, it)
        }
    }

    override suspend fun editDatasetName(dataset: Dataset, newName: String): Dataset {
        requireDatasetPresent(dataset)
        return dataset.copy(name = newName).also { datasets.update(dataset.id, it) }
    }

    override suspend fun addCategoryToDataset(dataset: Dataset, category: Category): Dataset {
        requireCategoryPresent(category)
        requireDatasetPresent(dataset)
        return if (dataset.categories.contains(category)) {
            dataset
        } else {
            dataset.copy(categories = dataset.categories + category).also {
                datasets.update(it.id, it)
            }
        }
    }

    override suspend fun updateUser(firebaseUser: FirebaseUser) =
        User(
            type = User.Type.FIREBASE,
            uid = firebaseUser.uid,
            email = firebaseUser.email,
            displayName = firebaseUser.displayName,
            isAdmin = false
        ).also { users.update(it.id.toString(), it) }

    override suspend fun setAdminAccess(firebaseUser: FirebaseUser, adminAccess: Boolean): User {
        val type = User.Type.FIREBASE
        val uid = firebaseUser.uid
        return User(
            type = type,
            uid = uid,
            email = firebaseUser.email,
            displayName = firebaseUser.displayName,
            isAdmin = adminAccess
        ).also { users.update(it.id.toString(), it) }
    }

    override suspend fun checkIsAdmin(user: User): Boolean {
        return user.isAdmin
    }

    override suspend fun getUser(type: User.Type, uid: String) =
        users.getById(User.Id(uid, type).toString())
}