All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.testerum.file_service.file.RecentProjectsFileService.kt Maven / Gradle / Ivy

package com.testerum.file_service.file

import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.guava.GuavaModule
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.afterburner.AfterburnerModule
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.testerum.common_kotlin.createDirectories
import com.testerum.common_kotlin.doesNotExist
import com.testerum.model.project.RecentProject
import com.testerum.settings.TesterumDirs
import java.time.LocalDateTime
import java.util.*
import kotlin.collections.ArrayList
import java.nio.file.Path as JavaPath

class RecentProjectsFileService (private val testerumDirs: TesterumDirs) {

    companion object {
        private val OBJECT_MAPPER: ObjectMapper = jacksonObjectMapper().apply {
            registerModule(AfterburnerModule())
            registerModule(JavaTimeModule())
            registerModule(GuavaModule())

            enable(SerializationFeature.INDENT_OUTPUT)
            setSerializationInclusion(JsonInclude.Include.NON_NULL)
            disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID)

            disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
            disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        }
    }

    fun save(recentProjects: List,
             recentProjectsFile: JavaPath) {
        val sortedRecentProjects = recentProjects.sortedByDescending { it.lastOpened }

        recentProjectsFile.parent?.createDirectories()
        OBJECT_MAPPER.writeValue(recentProjectsFile.toFile(), sortedRecentProjects)
    }

    fun load(recentProjectsFile: JavaPath): List {
        if (recentProjectsFile.doesNotExist) {
            return emptyList()
        }

        val recentProjects: List = OBJECT_MAPPER.readValue(recentProjectsFile.toFile())

        return recentProjects.sortedByDescending { it.lastOpened }
    }

    fun add(recentProject: RecentProject,
            recentProjectsFile: JavaPath) {
        val recentProjects = ArrayList()

        recentProjects += load(recentProjectsFile)
        recentProjects += recentProject

        val distinctRecentProjects = recentProjects.withoutDuplicates()

        save(distinctRecentProjects, recentProjectsFile)
    }

    fun updateLastOpened(projectRootDir: JavaPath,
                         recentProjectsFile: JavaPath): RecentProject {

        // to prevent Demo App to end-up in the recent projects
        if (projectRootDir == testerumDirs.getDemoTestsDir()) {
            return RecentProject(testerumDirs.getDemoTestsDir(), LocalDateTime.now())
        }

        val recentProject = getByPathOrAdd(projectRootDir, recentProjectsFile)
        val recentProjectToSave = recentProject.copy(
                lastOpened = LocalDateTime.now()
        )

        add(recentProjectToSave, recentProjectsFile)

        return recentProject
    }

    fun getByPathOrAdd(projectRootDir: JavaPath,
                       recentProjectsFile: JavaPath): RecentProject {
        val existingRecentProjects = load(recentProjectsFile)

        val normalizedPath = projectRootDir.toAbsolutePath().normalize()

        val existingProject = existingRecentProjects.find {
            it.path.toAbsolutePath().normalize() == normalizedPath
        }
        if (existingProject != null) {
            return existingProject
        }

        val newRecentProject = RecentProject(
                path = normalizedPath,
                lastOpened = LocalDateTime.now()
        )

        add(newRecentProject, recentProjectsFile)

        return newRecentProject
    }

    fun delete(projectRootDir: JavaPath,
               recentProjectsFile: JavaPath) {
        val recentProjects = ArrayList()
        recentProjects += load(recentProjectsFile)

        val normalizedPath = projectRootDir.toAbsolutePath().normalize()

        recentProjects.removeIf {
            it.path.toAbsolutePath().normalize() == normalizedPath
        }

        save(recentProjects, recentProjectsFile)
    }

    private fun MutableList.withoutDuplicates(): List {
        // not using "distinctBy()" because we want to keep a particular item: the one with the highest "lastOpened"
        val result = TreeMap()

        for (recentProject in this) {
            val normalizedPath = recentProject.path.toAbsolutePath().normalize()

            val existingRecentProject = result[normalizedPath]

            val shouldAdd = (existingRecentProject == null)
                    || (recentProject.lastOpened > existingRecentProject.lastOpened)

            if (shouldAdd) {
                result[normalizedPath] = recentProject
            }
        }

        return result.values.toList()
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy