@@ -11,6 +11,8 @@ class ModelImporter(private val root: INode) {
11
11
12
12
private lateinit var originalIdToRef: MutableMap <String , INodeReference >
13
13
private lateinit var originalIdToSpec: MutableMap <String , NodeData >
14
+ private lateinit var originalIdToParentSpec: MutableMap <String , NodeData >
15
+ private lateinit var existingNodeIds: MutableSet <String >
14
16
15
17
fun import (jsonFile : File ) {
16
18
require(jsonFile.exists())
@@ -21,12 +23,34 @@ class ModelImporter(private val root: INode) {
21
23
}
22
24
23
25
fun import (data : ModelData ) {
24
- originalIdToRef = mutableMapOf ()
26
+ existingNodeIds = mutableSetOf ()
27
+ collectExistingNodeIds(root)
28
+
25
29
originalIdToSpec = mutableMapOf ()
26
30
buildSpecIndex(data.root)
31
+
32
+ originalIdToParentSpec = mutableMapOf ()
33
+ buildParentSpecIndex(data.root)
34
+
27
35
syncNode(root, data.root)
36
+
37
+ originalIdToRef = mutableMapOf ()
28
38
buildRefIndex(root)
39
+
29
40
syncAllReferences(root, data.root)
41
+ syncAllChildOrders(root, data.root)
42
+ }
43
+
44
+ private fun collectExistingNodeIds (root : INode ) {
45
+ root.originalId()?.let { existingNodeIds.add(it) }
46
+ root.allChildren.forEach { collectExistingNodeIds(it) }
47
+ }
48
+
49
+ private fun buildParentSpecIndex (nodeData : NodeData ) {
50
+ for (child in nodeData.children) {
51
+ child.originalId()?.let { originalIdToParentSpec[it] = nodeData }
52
+ buildParentSpecIndex(child)
53
+ }
30
54
}
31
55
32
56
private fun buildRefIndex (node : INode ) {
@@ -66,28 +90,42 @@ class ModelImporter(private val root: INode) {
66
90
}
67
91
68
92
private fun syncChildNodes (node : INode , nodeData : NodeData ) {
69
- val toBeRemoved = mutableSetOf<INode >()
70
- val existingIds = node.allChildren.map { it.originalId() }
93
+ val specifiedNodes = nodeData.children.toSet()
94
+ val existingIds = node.allChildren.map { it.originalId() }.toSet()
95
+ val missingNodes = specifiedNodes.filter { ! existingIds.contains(it.originalId()) }
71
96
72
- val toBeAdded = nodeData.children.filter { ! existingIds.contains(it.id) }
97
+ val toBeMovedHere = missingNodes.filter { existingNodeIds.contains(it.originalId()) }.toSet()
98
+ val toBeAdded = missingNodes.subtract(toBeMovedHere)
73
99
74
100
toBeAdded.forEach {
75
101
val index = nodeData.children.indexOf(it)
76
102
val createdNode = node.addNewChild(it.role, index, it.concept?.let { s -> ConceptReference (s) })
77
103
createdNode.setPropertyValue(NodeData .idPropertyKey, it.originalId())
78
104
}
79
105
80
- for (child in node.allChildren) {
81
- val foundChildData: NodeData ? = originalIdToSpec[child.originalId()]
82
- if (foundChildData != null ) {
83
- syncNode(child, foundChildData)
84
- } else {
85
- toBeRemoved.add(child)
106
+ toBeMovedHere.forEach {
107
+ val target = originalIdToRef[it.originalId()]?.resolveNode(node.getArea())
108
+ if (target != null ) {
109
+ node.moveChild(it.role, - 1 , target)
86
110
}
87
111
}
88
112
113
+ val toBeRemoved = node.allChildren.filter { ! originalIdToSpec.contains(it.originalId()) }
89
114
toBeRemoved.forEach { node.removeChild(it) }
90
- syncChildOrder(node, nodeData)
115
+
116
+ node.allChildren.forEach {
117
+ val childData = originalIdToSpec[it.originalId()]
118
+ if (childData != null ) {
119
+ syncNode(it, childData)
120
+ }
121
+ }
122
+ }
123
+
124
+ private fun syncAllChildOrders (root : INode , rootData : NodeData ) {
125
+ syncChildOrder(root, rootData)
126
+ for ((node, data) in root.allChildren.zip(rootData.children)) {
127
+ syncAllChildOrders(node, data)
128
+ }
91
129
}
92
130
93
131
private fun syncChildOrder (node : INode , nodeData : NodeData ) {
0 commit comments