asfoury/projmag

View on GitHub
app/src/main/java/com/sdp13epfl2021/projmag/model/ImmutableProject.kt

Summary

Maintainability
B
6 hrs
Test Coverage
A
100%
package com.sdp13epfl2021.projmag.model

import android.os.Parcelable
import com.sdp13epfl2021.projmag.database.interfaces.ProjectId
import com.sdp13epfl2021.projmag.model.ImmutableProject.Companion.FieldNames.toSearchName
import kotlinx.parcelize.Parcelize
import java.util.*

sealed class Result<T>
data class Success<T>(val value: T) : Result<T>()
data class Failure<T>(val reason: String) : Result<T>()

@Parcelize
data class ImmutableProject(
    val id: String,
    val name: String,
    val lab: String,
    val authorId: String,
    val teacher: String,
    val TA: String,
    val nbParticipant: Int,
    val assigned: List<String>,
    val masterProject: Boolean,
    val bachelorProject: Boolean,
    val tags: List<String>,
    val isTaken: Boolean,
    val description: String,
    val videoUri: List<String> = listOf(),
    val allowedSections: List<String> = listOf(),
    val creationDate: Date = Date()
) : Parcelable {
    companion object {
        object FieldNames {
            fun String.toSearchName(): String = "${this}-search"
            const val NAME = "name"
            const val LAB = "lab"
            const val AUTHOR_ID = "authorID"
            const val TEACHER = "teacher"
            const val TA = "TA"
            const val NB_PARTICIPANT = "nbParticipant"
            const val ASSIGNED = "assigned"
            const val MASTER_PROJECT = "masterProject"
            const val BACHELOR_PROJECT = "bachelorProject"
            const val TAGS = "tags"
            const val IS_TAKEN = "isTaken"
            const val DESCRIPTION = "description"
            const val VIDEO_URI = "videoURI"
            const val ALLOWED_SECTIONS = "allowedSections"
            const val CREATION_DATE = "creationDate"
        }

        const val MAX_PROJECT_NAME_SIZE = 120
        const val MAX_NAME_SIZE = 40
        const val MAX_DESCRIPTION_SIZE = 4000
        private const val MAX_STUDENT_NUMBER = 10

        /**
         * Function that allows create a Project
         * returns a project wrapped in a success wrapper, or a failure with the explanation wrapped as a string
         *
         * @param id : project id from firebase
         * @param name : name of the project
         * @param lab : lab of the project
         * @param teacher : person responsible for the lab
         * @param TA : person responsible for the project
         * @param nbParticipant : number of participants
         * @param assigned : list of the assigned students
         * @param masterProject : is this project available for a 12 credits master project
         * @param bachelorProject : is this project available as a bachelor semester project
         * @param tags : tags associated to the project
         * @param isTaken : Is this project already taken
         * @param description : description of the project
         */

        fun build(
            id: String,
            name: String,
            lab: String,
            authorId: String,
            teacher: String,
            TA: String,
            nbParticipant: Int,
            assigned: List<String>,
            masterProject: Boolean,
            bachelorProject: Boolean,
            tags: List<String>,
            isTaken: Boolean,
            description: String,
            videoURI: List<String> = listOf(),
            allowedSections: List<String> = listOf(),
            creationDate: Date = Date()
        ): Result<ImmutableProject> {
            return when {
                name.length > MAX_PROJECT_NAME_SIZE -> Failure("name is more than $MAX_PROJECT_NAME_SIZE characters")
                lab.length > MAX_NAME_SIZE -> Failure("lab name is more than $MAX_NAME_SIZE characters")
                TA.length > MAX_NAME_SIZE -> Failure("project manager name is more than $MAX_NAME_SIZE characters")
                teacher.length > MAX_NAME_SIZE -> Failure("teacher name is more than $MAX_NAME_SIZE characters")
                description.length > MAX_DESCRIPTION_SIZE -> Failure("description  is more than $MAX_DESCRIPTION_SIZE characters")
                nbParticipant > MAX_STUDENT_NUMBER -> Failure("max student number for a project is set to $MAX_STUDENT_NUMBER")
                assigned.size > nbParticipant -> Failure(
                    "there are ${assigned.size} " +
                            "students currently assigned but only $nbParticipant allowed to work for the project"
                )
                //!sectionsManager.isListValid(allowedSections) -> Failure("a section in the section list doesn't exist $allowedSections")
                //!tagsManager.isListOfStringsValidTags(tags) -> Failure("a tag in the tag list doesn't exist $tags")

                else -> Success(
                    ImmutableProject(
                        id,
                        name,
                        lab,
                        authorId,
                        teacher,
                        TA,
                        nbParticipant,
                        assigned,
                        masterProject,
                        bachelorProject,
                        tags,
                        isTaken,
                        description,
                        videoURI,
                        allowedSections,
                        creationDate
                    )
                )
            }
        }

        /**
         * Build a project from the given map
         *
         * @param map : a map containing all fields of the project
         * @param projectId : the id of the project
         *
         * @return an ImmutableProject if the build succeed, null otherwise
         */
        @Suppress("UNCHECKED_CAST")
        fun buildFromMap(map: Map<String, Any?>, projectId: ProjectId): ImmutableProject? {
            try {
                val result = build(
                    id = projectId,
                    name = map[FieldNames.NAME] as String,
                    lab = map[FieldNames.LAB] as String,
                    authorId = map[FieldNames.AUTHOR_ID] as String,
                    teacher = map[FieldNames.TEACHER] as String,
                    TA = map[FieldNames.TA] as String,
                    nbParticipant = (map[FieldNames.NB_PARTICIPANT] as Number).toInt(),
                    assigned = map[FieldNames.ASSIGNED] as List<String>,
                    masterProject = map[FieldNames.MASTER_PROJECT] as Boolean,
                    bachelorProject = map[FieldNames.BACHELOR_PROJECT] as Boolean,
                    tags = map[FieldNames.TAGS] as List<String>,
                    isTaken = map[FieldNames.IS_TAKEN] as Boolean,
                    description = map[FieldNames.DESCRIPTION] as String,
                    videoURI = map[FieldNames.VIDEO_URI] as List<String>,
                    allowedSections = map[FieldNames.ALLOWED_SECTIONS] as List<String>,
                    creationDate = Date(map[FieldNames.CREATION_DATE] as Long)
                )
                return when (result) {
                    is Success -> result.value
                    is Failure -> {
                        println(result.reason)
                        null
                    }
                }
                /* These two exceptions occur only with corrupted Projects so should be ignored */
            } catch (e: NullPointerException) {
                e.printStackTrace()
                return null
            } catch (e: ClassCastException) {
                e.printStackTrace()
                return null
            }
        }
    }


    /**
     * Function that allows copying of a project and modifying only the fields that you wish to modify
     * returns a project wrapped in a success wrapper, or a failure with the explanation wrapped as a string
     *
     * @param id : project id from firebase
     * @param name : name of the project
     * @param lab : lab of the project
     * @param teacher : person responsible for the lab
     * @param TA : person responsible for the project
     * @param nbParticipant : number of participants
     * @param assigned : list of the assigned students
     * @param masterProject : is this project available for a 12 credits master project
     * @param bachelorProject : is this project available as a bachelor semester project
     * @param tags : tags associated to the project
     * @param isTaken : Is this project already taken
     * @param description : description of the project
     * @param creationDate : the date of the creation
     */
    fun buildCopy(
        id: String = this.id,
        name: String = this.name,
        lab: String = this.lab,
        authorId: String = this.authorId,
        teacher: String = this.teacher,
        TA: String = this.TA,
        nbParticipant: Int = this.nbParticipant,
        assigned: List<String> = this.assigned,
        masterProject: Boolean = this.masterProject,
        bachelorProject: Boolean = this.bachelorProject,
        tags: List<String> = this.tags,
        isTaken: Boolean = this.isTaken,
        description: String = this.description,
        videoURI: List<String> = this.videoUri,
        allowedSections: List<String> = this.allowedSections,
        creationDate: Date = this.creationDate
    ) = build(
        id,
        name,
        lab,
        authorId,
        teacher,
        TA,
        nbParticipant,
        assigned,
        masterProject,
        bachelorProject,
        tags,
        isTaken,
        description,
        videoURI,
        allowedSections,
        creationDate
    )

    /**
     *  Give a Map<String,Any> the maps name of members to their values.
     */
    fun toMapString() = hashMapOf(
        FieldNames.NAME to name,
        FieldNames.NAME.toSearchName() to name.toLowerCase(Locale.ROOT).split(" "),
        FieldNames.LAB to lab,
        FieldNames.LAB.toSearchName() to lab.toLowerCase(Locale.ROOT),
        FieldNames.AUTHOR_ID to authorId,
        FieldNames.TEACHER to teacher,
        FieldNames.TEACHER.toSearchName() to teacher.toLowerCase(Locale.ROOT).split(" "),
        FieldNames.TA to TA,
        FieldNames.TA.toSearchName() to TA.toLowerCase(Locale.ROOT),
        FieldNames.NB_PARTICIPANT to nbParticipant,
        FieldNames.ASSIGNED to assigned,
        FieldNames.MASTER_PROJECT to masterProject,
        FieldNames.BACHELOR_PROJECT to bachelorProject,
        FieldNames.TAGS to tags,
        FieldNames.TAGS.toSearchName() to tags.map { it.toLowerCase(Locale.ROOT) },
        FieldNames.IS_TAKEN to isTaken,
        FieldNames.DESCRIPTION to description,
        FieldNames.VIDEO_URI to videoUri,
        FieldNames.ALLOWED_SECTIONS to allowedSections,
        FieldNames.CREATION_DATE to creationDate.time
    )


}