@@ -34,7 +34,6 @@ class ModelImporter(private val root: INode, val stats: ImportStats? = null) {
34
34
buildRefIndex(root)
35
35
36
36
syncAllReferences(root, data.root)
37
- syncAllChildOrders(root, data.root)
38
37
}
39
38
40
39
private fun buildExistingIndex (root : INode ) {
@@ -91,24 +90,27 @@ class ModelImporter(private val root: INode, val stats: ImportStats? = null) {
91
90
val existingIds = node.allChildren.map { it.originalId() }.toSet()
92
91
val missingNodes = specifiedNodes.filter { ! existingIds.contains(it.originalId()) }
93
92
94
- val toBeMovedHere = missingNodes. filter { originalIdToExisting.containsKey (it.originalId()) }.toSet()
95
- val toBeAdded = missingNodes.subtract(toBeMovedHere)
93
+ val toBeRemoved = node.allChildren. filter { ! originalIdToSpec.contains (it.originalId()) }
94
+ toBeRemoved.forEach { node.removeChildWithStats(it) }
96
95
97
- toBeAdded.forEach {
98
- val index = nodeData.children.indexOf(it)
99
- node.addNewChildWithStats(it, index)
100
- }
96
+ val toBeMovedAwayFromHere = existingIds.subtract(specifiedNodes.map { it.originalId() }.toSet())
97
+
98
+ syncExistingChildOrder(node, nodeData, existingIds, toBeMovedAwayFromHere)
101
99
100
+ val toBeMovedHere = missingNodes.filter { originalIdToExisting.containsKey(it.originalId()) }.toSet()
102
101
toBeMovedHere.forEach {
103
102
val actualNode = originalIdToExisting[it.originalId()]
104
- val targetIndex = it.getIndexWithinRole(nodeData)
103
+ val targetIndex = it.getIndexWithinRole(nodeData,existingIds.size - 1 )
105
104
if (actualNode != null ) {
106
105
node.moveChildWithStats(it.role, targetIndex, actualNode)
107
106
}
108
107
}
109
108
110
- val toBeRemoved = node.allChildren.filter { ! originalIdToSpec.contains(it.originalId()) }
111
- toBeRemoved.forEach { node.removeChildWithStats(it) }
109
+ val toBeAdded = missingNodes.subtract(toBeMovedHere)
110
+ toBeAdded.forEach {
111
+ val index = it.getIndexWithinRole(nodeData, existingIds.size - 1 )
112
+ node.addNewChildWithStats(it, index)
113
+ }
112
114
113
115
node.allChildren.forEach {
114
116
val childData = originalIdToSpec[it.originalId()]
@@ -118,34 +120,34 @@ class ModelImporter(private val root: INode, val stats: ImportStats? = null) {
118
120
}
119
121
}
120
122
121
- private fun syncAllChildOrders (root : INode , rootData : NodeData ) {
122
- syncChildOrder(root, rootData)
123
- for ((node, data) in root.allChildren zip rootData.children) {
124
- syncAllChildOrders(node, data)
125
- }
126
- }
127
-
128
- private fun syncChildOrder (node : INode , nodeData : NodeData ) {
123
+ private fun syncExistingChildOrder (
124
+ node : INode ,
125
+ nodeData : NodeData ,
126
+ existingIds : Set <String ?>,
127
+ toBeMovedAwayFromHere : Set <String ?>
128
+ ) {
129
129
val existingChildren = node.allChildren.toList()
130
130
val specifiedChildren = nodeData.children
131
- require(existingChildren.size == specifiedChildren.size)
131
+ require(existingChildren.size <= specifiedChildren.size)
132
+
133
+ val filteredSpecifiedChildren = specifiedChildren.filter { existingIds.contains(it.originalId()) }
132
134
133
135
val targetIndices = HashMap <String ?, Int >(nodeData.children.size)
134
- for (specifiedChild in specifiedChildren ) {
135
- val index = specifiedChild.getIndexWithinRole(nodeData )
136
- targetIndices[specifiedChild.originalId()] = index
136
+ for (specifiedChild in filteredSpecifiedChildren ) {
137
+ val index = filteredSpecifiedChildren.filter { it.role == node.roleInParent }.indexOf(specifiedChild )
138
+ targetIndices[specifiedChild.originalId()] = minOf( index, existingChildren.size - 1 )
137
139
}
138
140
139
141
for ((index, child) in existingChildren.withIndex()) {
140
142
val targetIndex = targetIndices[child.originalId()] ? : - 1
141
- if (targetIndex != index) {
143
+ if (targetIndex != index && ! toBeMovedAwayFromHere.contains(child.originalId()) ) {
142
144
node.moveChildWithStats(child.roleInParent, targetIndex, child)
143
145
}
144
146
}
145
147
}
146
148
147
- private fun NodeData.getIndexWithinRole (parent : NodeData ) : Int {
148
- return parent.children.filter { it.role == this .role }.indexOf(this )
149
+ private fun NodeData.getIndexWithinRole (parent : NodeData , maxIndex : Int ) : Int {
150
+ return minOf( parent.children.filter { it.role == this .role }.indexOf(this ), maxIndex )
149
151
}
150
152
151
153
private fun INode.originalId (): String? {
0 commit comments