1
1
package org.modelix.model.sync
2
2
3
- import org.modelix.model.api.*
3
+ import org.modelix.model.api.ConceptReference
4
+ import org.modelix.model.api.INode
5
+ import org.modelix.model.api.INodeReference
4
6
import org.modelix.model.data.ModelData
5
7
import org.modelix.model.data.NodeData
6
8
import java.io.File
7
9
8
- class ModelImporter (private val branch : IBranch ) {
10
+ class ModelImporter (private val root : INode ) {
9
11
10
12
private lateinit var originalIdToRef: MutableMap <String , INodeReference >
13
+ private lateinit var originalIdToSpec: MutableMap <String , NodeData >
11
14
12
15
fun import (jsonFile : File ) {
13
16
require(jsonFile.exists())
@@ -19,59 +22,72 @@ class ModelImporter(private val branch: IBranch) {
19
22
20
23
fun import (data : ModelData ) {
21
24
originalIdToRef = mutableMapOf ()
22
- branch.runWrite {
23
- val rootNode = branch.getRootNode()
24
- if (rootNode.allChildren.none()) {
25
- data.load(branch)
26
- return @runWrite
27
- }
28
- buildRefIndex(rootNode)
29
- syncNode(rootNode, data.root)
30
- }
25
+ originalIdToSpec = mutableMapOf ()
26
+ buildSpecIndex(data.root)
27
+ syncNode(root, data.root)
28
+ buildRefIndex(root)
29
+ syncAllReferences(root, data.root)
31
30
}
32
31
33
32
private fun buildRefIndex (node : INode ) {
34
33
node.originalId()?.let { originalIdToRef[it] = node.reference }
35
34
node.allChildren.forEach { buildRefIndex(it) }
36
35
}
37
36
37
+ private fun buildSpecIndex (nodeData : NodeData ) {
38
+ nodeData.originalId()?.let { originalIdToSpec[it] = nodeData }
39
+ nodeData.children.forEach { buildSpecIndex(it) }
40
+ }
41
+
38
42
private fun syncNode (node : INode , nodeData : NodeData ) {
39
43
syncProperties(node, nodeData)
40
- syncReferences(node, nodeData)
41
44
syncChildNodes(node, nodeData)
42
45
}
43
46
44
47
private fun syncProperties (node : INode , nodeData : NodeData ) {
45
48
nodeData.properties.forEach { node.setPropertyValue(it.key, it.value) }
49
+ val toBeRemoved = node.getPropertyRoles().toSet()
50
+ .subtract(nodeData.properties.keys)
51
+ .filter { it != NodeData .idPropertyKey }
52
+ toBeRemoved.forEach { node.setPropertyValue(it, null ) }
53
+ }
54
+
55
+ private fun syncAllReferences (root : INode , rootData : NodeData ) {
56
+ syncReferences(root, rootData)
57
+ for ((node, data) in root.allChildren.zip(rootData.children)) {
58
+ syncAllReferences(node, data)
59
+ }
46
60
}
47
61
48
62
private fun syncReferences (node : INode , nodeData : NodeData ) {
49
63
nodeData.references.forEach { node.setReferenceTarget(it.key, originalIdToRef[it.value]) }
64
+ val toBeRemoved = node.getReferenceRoles().toSet().subtract(nodeData.references.keys)
65
+ toBeRemoved.forEach { node.setPropertyValue(it, null ) }
50
66
}
51
67
52
68
private fun syncChildNodes (node : INode , nodeData : NodeData ) {
53
69
val toBeRemoved = mutableSetOf<INode >()
54
- val existingIds = mutableSetOf<String >()
70
+ val existingIds = node.allChildren.map { it.originalId() }
71
+
72
+ val toBeAdded = nodeData.children.filter { ! existingIds.contains(it.id) }
73
+
74
+ toBeAdded.forEach {
75
+ val index = nodeData.children.indexOf(it)
76
+ val createdNode = node.addNewChild(it.role, index, it.concept?.let { s -> ConceptReference (s) })
77
+ createdNode.setPropertyValue(NodeData .idPropertyKey, it.originalId())
78
+ }
55
79
56
80
for (child in node.allChildren) {
57
- child.originalId()?.let { existingIds.add(it) }
58
- val foundChildData: NodeData ? = nodeData.children.find { it.id == child.originalId() }
81
+ val foundChildData: NodeData ? = originalIdToSpec[child.originalId()]
59
82
if (foundChildData != null ) {
60
83
syncNode(child, foundChildData)
61
84
} else {
62
85
toBeRemoved.add(child)
63
86
}
64
87
}
65
88
66
- val toBeAdded = nodeData.children.filter { ! existingIds.contains(it.id) }
67
-
68
- toBeAdded.forEach {
69
- val index = nodeData.children.indexOf(it)
70
- val createdNode = node.addNewChild(it.role, index, it.concept?.let { s -> ConceptReference (s) })
71
- createdNode.setPropertyValue(NodeData .idPropertyKey, it.originalId())
72
- }
73
89
toBeRemoved.forEach { node.removeChild(it) }
74
- syncChildOrder(node, nodeData)
90
+ syncChildOrder(node, nodeData)
75
91
}
76
92
77
93
private fun syncChildOrder (node : INode , nodeData : NodeData ) {
0 commit comments