Skip to content

Commit d52d6a4

Browse files
committed
fix(model-sync-lib): nodes moved across parents are no longer deleted and recreated
1 parent 856ac28 commit d52d6a4

File tree

2 files changed

+49
-17
lines changed

2 files changed

+49
-17
lines changed

model-sync-lib/src/main/kotlin/org/modelix/model/sync/ModelImporter.kt

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class ModelImporter(private val root: INode) {
1111

1212
private lateinit var originalIdToRef: MutableMap<String, INodeReference>
1313
private lateinit var originalIdToSpec: MutableMap<String, NodeData>
14+
private lateinit var originalIdToParentSpec: MutableMap<String, NodeData>
15+
private lateinit var existingNodeIds: MutableSet<String>
1416

1517
fun import(jsonFile: File) {
1618
require(jsonFile.exists())
@@ -21,12 +23,34 @@ class ModelImporter(private val root: INode) {
2123
}
2224

2325
fun import(data: ModelData) {
24-
originalIdToRef = mutableMapOf()
26+
existingNodeIds = mutableSetOf()
27+
collectExistingNodeIds(root)
28+
2529
originalIdToSpec = mutableMapOf()
2630
buildSpecIndex(data.root)
31+
32+
originalIdToParentSpec = mutableMapOf()
33+
buildParentSpecIndex(data.root)
34+
2735
syncNode(root, data.root)
36+
37+
originalIdToRef = mutableMapOf()
2838
buildRefIndex(root)
39+
2940
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+
}
3054
}
3155

3256
private fun buildRefIndex(node: INode) {
@@ -66,28 +90,42 @@ class ModelImporter(private val root: INode) {
6690
}
6791

6892
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()) }
7196

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)
7399

74100
toBeAdded.forEach {
75101
val index = nodeData.children.indexOf(it)
76102
val createdNode = node.addNewChild(it.role, index, it.concept?.let { s -> ConceptReference(s) })
77103
createdNode.setPropertyValue(NodeData.idPropertyKey, it.originalId())
78104
}
79105

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)
86110
}
87111
}
88112

113+
val toBeRemoved = node.allChildren.filter { !originalIdToSpec.contains(it.originalId()) }
89114
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+
}
91129
}
92130

93131
private fun syncChildOrder(node: INode, nodeData: NodeData) {

model-sync-lib/src/test/kotlin/org/modelix/model/sync/ModelExporterTest.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ class ModelExporterTest {
4343
}
4444
}
4545

46-
branch.runRead {
47-
for (child in branch.getRootNode().allChildren) {
48-
println(child.getReferenceRoles())
49-
}
50-
}
51-
5246
assert(outputFile.exists())
5347
assertEquals(model, ModelData.fromJson(outputFile.readText()))
5448
}

0 commit comments

Comments
 (0)