[workspace model] provide implementation of FacetManager which stores data in workspa...
[idea/community.git] / platform / workspaceModel-ide / src / com / intellij / workspace / legacyBridge / libraries / libraries / LegacyBridgeProjectModifiableLibraryTableImpl.kt
1 package com.intellij.workspace.legacyBridge.libraries.libraries
2
3 import com.intellij.openapi.project.Project
4 import com.intellij.openapi.roots.ProjectModelExternalSource
5 import com.intellij.openapi.roots.libraries.Library
6 import com.intellij.openapi.roots.libraries.LibraryProperties
7 import com.intellij.openapi.roots.libraries.LibraryTable
8 import com.intellij.openapi.roots.libraries.PersistentLibraryKind
9 import com.intellij.openapi.util.Disposer
10 import com.intellij.workspace.api.*
11 import com.intellij.workspace.ide.IdeUiEntitySource
12 import com.intellij.workspace.ide.WorkspaceModel
13 import com.intellij.workspace.ide.toEntitySource
14 import com.intellij.workspace.legacyBridge.typedModel.library.LibraryViaTypedEntity
15
16 internal class LegacyBridgeProjectModifiableLibraryTableImpl(
17   originalStorage: TypedEntityStorage,
18   private val libraryTable: LegacyBridgeProjectLibraryTableImpl,
19   private val project: Project,
20   diff: TypedEntityStorageBuilder = TypedEntityStorageBuilder.from(originalStorage)
21 ) : LegacyBridgeModifiableBase(diff), LibraryTable.ModifiableModel {
22
23   private val myLibrariesToAdd = mutableListOf<LegacyBridgeLibraryImpl>()
24   private val myLibrariesToRemove = mutableListOf<Library>()
25
26   private val librariesValue = CachedValueWithParameter { _: TypedEntityStorage, (librariesToAdd, librariesToRemove): Pair<List<Library>, List<Library>> ->
27     val libs = libraryTable.libraries.toMutableList()
28     libs.removeAll(librariesToRemove)
29     libs.addAll(librariesToAdd)
30     return@CachedValueWithParameter libs.map { it.name to it }.toMap() to libs.toTypedArray()
31   }
32
33   private val libraries
34     get() = WorkspaceModel.getInstance(project).entityStore.cachedValue(librariesValue, myLibrariesToAdd to myLibrariesToRemove)
35
36 /*  private fun getLibraryModifiableModel(library: LibraryViaTypedEntity,
37                                         diff: TypedEntityStorageBuilder): LegacyBridgeLibraryModifiableModelImpl {
38
39     return LegacyBridgeLibraryModifiableModelImpl(
40       originalLibrary = library,
41       diff = diff,
42       committer = { _, diffBuilder ->
43         diff.addDiff(diffBuilder)
44       })
45   }*/
46
47   override fun createLibrary(name: String?): Library = createLibrary(name = name, type = null)
48
49   override fun createLibrary(name: String?, type: PersistentLibraryKind<out LibraryProperties<*>>?): Library =
50     createLibrary(name = name, type = type, externalSource = null)
51
52   override fun createLibrary(name: String?,
53                              type: PersistentLibraryKind<out LibraryProperties<*>>?,
54                              externalSource: ProjectModelExternalSource?): Library {
55
56     if (name.isNullOrBlank()) error("Project Library must have a name")
57
58     assertModelIsLive()
59
60     val libraryTableId = LibraryTableId.ProjectLibraryTableId
61
62     val libraryEntity = diff.addLibraryEntity(
63       roots = emptyList(),
64       tableId = LibraryTableId.ProjectLibraryTableId,
65       name = name,
66       excludedRoots = emptyList(),
67       source = if (externalSource != null) externalSource.toEntitySource() else IdeUiEntitySource
68     )
69
70     if (type != null) {
71       diff.addLibraryPropertiesEntity(
72         library = libraryEntity,
73         libraryType = type.kindId,
74         propertiesXmlTag = null,
75         source = libraryEntity.entitySource
76       )
77     }
78
79     return LegacyBridgeLibraryImpl(
80       libraryTable = libraryTable,
81       project = project,
82       initialId = LibraryId(name, libraryTableId),
83       initialEntityStore = entityStoreOnDiff,
84       parent = libraryTable
85     ).also { libraryImpl ->
86       libraryImpl.modifiableModelFactory = { librarySnapshot, diff ->
87         LegacyBridgeLibraryModifiableModelImpl(
88           originalLibrary = libraryImpl,
89           originalLibrarySnapshot = librarySnapshot,
90           diff = diff,
91           committer = { _, diffBuilder ->
92             this.diff.addDiff(diffBuilder)
93           }
94         )
95       }
96       myLibrariesToAdd.add(libraryImpl)
97     }
98   }
99
100   override fun removeLibrary(library: Library) {
101     assertModelIsLive()
102
103     val currentStorage = entityStoreOnDiff.current
104
105     val entityId = when (library) {
106       is LegacyBridgeLibraryImpl -> library.entityId
107       is LibraryViaTypedEntity -> library.libraryEntity.persistentId()
108       else -> error("Unknown libraryImpl class: ${library.javaClass.simpleName}")
109     }
110
111     val libraryEntity = currentStorage.resolve(entityId)
112     if (libraryEntity != null) {
113       diff.removeEntity(libraryEntity)
114       myLibrariesToRemove.add(library)
115     }
116   }
117
118   override fun commit() {
119     assertModelIsLive()
120     modelIsCommittedOrDisposed = true
121
122     libraryTable.setNewLibraryInstances(myLibrariesToAdd)
123     WorkspaceModel.getInstance(project).updateProjectModel {
124       it.addDiff(diff)
125     }
126   }
127
128   override fun getLibraryIterator(): Iterator<Library> = libraries.second.iterator()
129   override fun getLibraryByName(name: String): Library? = libraries.first[name]
130   override fun getLibraries(): Array<Library> = libraries.second
131
132   override fun dispose() {
133     modelIsCommittedOrDisposed = true
134
135     myLibrariesToAdd.forEach { Disposer.dispose(it) }
136     myLibrariesToAdd.clear()
137   }
138
139   override fun isChanged(): Boolean = !diff.isEmpty()
140 }