[workspace model] provide implementation of FacetManager which stores data in workspa...
[idea/community.git] / platform / workspaceModel-ide / src / com / intellij / workspace / ide / jpsEntitySources.kt
1 package com.intellij.workspace.ide
2
3 import com.intellij.openapi.project.Project
4 import com.intellij.openapi.roots.ProjectModelExternalSource
5 import com.intellij.project.isDirectoryBased
6 import com.intellij.util.PathUtil
7 import com.intellij.workspace.api.EntitySource
8 import com.intellij.workspace.api.VirtualFileUrl
9 import com.intellij.workspace.api.VirtualFileUrlManager
10 import org.jetbrains.jps.util.JpsPathUtil
11 import java.util.concurrent.atomic.AtomicInteger
12
13 /**
14  * Represents a file/directory where IntelliJ project is stored.
15  */
16 sealed class JpsProjectStoragePlace {
17   abstract val baseDirectoryUrl: String
18   abstract fun exists(): Boolean
19
20   data class DirectoryBased(val projectDir: VirtualFileUrl) : JpsProjectStoragePlace() {
21     override val baseDirectoryUrl: String
22       get() = projectDir.url
23
24     override fun exists() = JpsPathUtil.urlToFile(projectDir.url).exists()
25   }
26   data class FileBased(val iprFile: VirtualFileUrl) : JpsProjectStoragePlace() {
27     override val baseDirectoryUrl: String
28       get() = PathUtil.getParentPath(iprFile.url)
29
30     override fun exists() = JpsPathUtil.urlToFile(iprFile.url).exists()
31   }
32 }
33
34 /**
35  * Represents an xml file containing configuration of IntelliJ IDEA project in JPS format (*.ipr file or *.xml file under .idea directory)
36  */
37 sealed class JpsFileEntitySource : EntitySource {
38   abstract val projectPlace: JpsProjectStoragePlace
39
40   /**
41    * Represents a specific xml file containing configuration of some entities of IntelliJ IDEA project.
42    */
43   data class ExactFile(val file: VirtualFileUrl, override val projectPlace: JpsProjectStoragePlace) : JpsFileEntitySource()
44
45   /**
46    * Represents an xml file located in the specified [directory] which contains configuration of some entities of IntelliJ IDEA project.
47    * The file name is automatically derived from the entity name.
48    */
49   data class FileInDirectory(val directory: VirtualFileUrl, override val projectPlace: JpsProjectStoragePlace) : JpsFileEntitySource() {
50     /**
51      * Automatically generated value which is used to distinguish different files in [directory]. The actual name is stored in serialization
52      * structures and may change if name of the corresponding entity has changed.
53      */
54     val fileNameId: Int = nextId.getAndIncrement()
55
56     companion object {
57       private val nextId = AtomicInteger()
58     }
59
60     override fun equals(other: Any?): Boolean {
61       if (this === other) return true
62       return other is FileInDirectory && directory == other.directory && projectPlace == other.projectPlace && fileNameId == other.fileNameId
63     }
64
65     override fun hashCode(): Int {
66       return directory.hashCode() * 31 * 31 + projectPlace.hashCode() * 31 + fileNameId
67     }
68   }
69 }
70
71 data class ExternalEntitySource(val displayName: String, val id: String) : EntitySource
72
73 fun ProjectModelExternalSource.toEntitySource() = ExternalEntitySource(displayName, id)
74
75 /**
76  * Represents entities added by user in IDE (either via Project Structure or Settings dialog, or by invoking an action like 'Create Library from Files').
77  */
78 // TODO It's required to resolve conflicts on library save when the file to write library to is not determined yet
79 object IdeUiEntitySource : EntitySource
80
81 /**
82  * Returns `null` for the default project
83  */
84 val Project.storagePlace: JpsProjectStoragePlace?
85   get() = if (isDirectoryBased) {
86     basePath?.let { JpsProjectStoragePlace.DirectoryBased(VirtualFileUrlManager.fromPath(it)) }
87   }
88   else {
89     projectFilePath?.let { JpsProjectStoragePlace.FileBased(VirtualFileUrlManager.fromPath(it)) }
90   }