[workspace model] provide implementation of FacetManager which stores data in workspa...
[idea/community.git] / platform / workspaceModel-ide / src / com / intellij / workspace / legacyBridge / facet / ModifiableFacetModelViaWorkspaceModel.kt
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.workspace.legacyBridge.facet
3
4 import com.intellij.facet.Facet
5 import com.intellij.facet.ModifiableFacetModel
6 import com.intellij.facet.impl.FacetUtil
7 import com.intellij.openapi.Disposable
8 import com.intellij.openapi.roots.ProjectModelExternalSource
9 import com.intellij.openapi.util.Disposer
10 import com.intellij.openapi.util.JDOMUtil
11 import com.intellij.util.containers.ContainerUtil
12 import com.intellij.workspace.api.*
13 import com.intellij.workspace.ide.WorkspaceModel
14 import com.intellij.workspace.ide.toEntitySource
15 import com.intellij.workspace.legacyBridge.intellij.LegacyBridgeModule
16
17 internal class ModifiableFacetModelViaWorkspaceModel(private val initialStorage: TypedEntityStorage,
18                                                      private val diff: TypedEntityStorageDiffBuilder,
19                                                      legacyBridgeModule: LegacyBridgeModule,
20                                                      private val facetManager: FacetManagerViaWorkspaceModel)
21   : FacetModelViaWorkspaceModel(legacyBridgeModule), ModifiableFacetModel {
22   private val listeners: MutableList<ModifiableFacetModel.Listener> = ContainerUtil.createLockFreeCopyOnWriteList()
23
24   init {
25     populateFrom(facetManager.model)
26   }
27
28   private fun getModuleEntity() = initialStorage.resolve(legacyBridgeModule.moduleEntityId)!!
29
30   override fun addFacet(facet: Facet<*>) {
31     addFacet(facet, null)
32   }
33
34   override fun addFacet(facet: Facet<*>, externalSource: ProjectModelExternalSource?) {
35     val moduleEntity = getModuleEntity()
36     val source = externalSource?.toEntitySource() ?: moduleEntity.entitySource
37     val facetConfigurationXml = FacetUtil.saveFacetConfiguration(facet)?.let { JDOMUtil.write(it) }
38     val underlyingEntity = facet.underlyingFacet?.let { entityToFacet.inverse()[it]!! }
39     val entity = diff.addFacetEntity(facet.name, facet.type.stringId, facetConfigurationXml, moduleEntity, underlyingEntity, source)
40     entityToFacet[entity] = facet
41     facetsChanged()
42   }
43
44   override fun removeFacet(facet: Facet<*>?) {
45     val facetEntity = entityToFacet.inverse()[facet] ?: return
46     removeFacetEntityWithSubFacets(facetEntity)
47     facetsChanged()
48   }
49
50   private fun removeFacetEntityWithSubFacets(entity: FacetEntity) {
51     entity.subFacets.forEach {
52       removeFacetEntityWithSubFacets(it)
53     }
54     entityToFacet.remove(entity)
55     diff.removeEntity(entity)
56   }
57
58   override fun rename(facet: Facet<*>, newName: String) {
59     val entity = entityToFacet.inverse()[facet]!!
60     val newEntity = diff.modifyEntity(ModifiableFacetEntity::class.java, entity) {
61       this.name = newName
62     }
63     entityToFacet.inverse()[facet] = newEntity
64     facetsChanged()
65   }
66
67   override fun getNewName(facet: Facet<*>): String? {
68     val entity = entityToFacet.inverse()[facet]!!
69     return entity.name
70   }
71
72   override fun commit() {
73     facetManager.model.populateFrom(entityToFacet)
74     val moduleDiff = legacyBridgeModule.diff
75     if (moduleDiff != null) {
76       moduleDiff.addDiff(diff)
77     }
78     else {
79       WorkspaceModel.getInstance(legacyBridgeModule.project).updateProjectModel {
80         it.addDiff(diff)
81       }
82     }
83   }
84
85   override fun isModified(): Boolean {
86     return !diff.isEmpty()
87   }
88
89   override fun isNewFacet(facet: Facet<*>): Boolean {
90     val entity = entityToFacet.inverse()[facet]
91     return entity != null && initialStorage.resolve(entity.persistentId()) == null
92   }
93
94   override fun addListener(listener: ModifiableFacetModel.Listener, parentDisposable: Disposable) {
95     listeners += listener
96     Disposer.register(parentDisposable, Disposable { listeners -= listener })
97   }
98
99   override fun facetsChanged() {
100     super.facetsChanged()
101     listeners.forEach { it.onChanged() }
102   }
103 }