@@ -30,16 +30,37 @@ import org.modelix.model.api.remove
30
30
31
31
interface INonExistingNode {
32
32
fun getParent (): INonExistingNode ?
33
+ fun getContainmentLink (): IChildLink ?
34
+ fun index (): Int
33
35
fun replaceNode (subConcept : IConcept ? ): INode
34
36
fun getOrCreateNode (subConcept : IConcept ? ): INode
35
37
fun expectedConcept (): IConcept ?
36
38
fun getVisibleReferenceTargets (link : IReferenceLink ): List <INode >
37
39
}
38
40
39
- data class SpecializedNonExistingNode (val node : INonExistingNode , val subConcept : IConcept ): INonExistingNode {
40
- override fun getParent (): INonExistingNode ? {
41
- TODO (" Not yet implemented" )
41
+ fun INonExistingNode.ancestors (includeSelf : Boolean = false): Sequence <INonExistingNode > {
42
+ return generateSequence(if (includeSelf) this else getParent()) { it.getParent() }
43
+ }
44
+
45
+ fun INonExistingNode.commonAncestor (otherNode : INonExistingNode ): INonExistingNode ? {
46
+ val ancestors1 = HashSet <INonExistingNode >()
47
+ val ancestors2 = HashSet <INonExistingNode >()
48
+
49
+ for (ancestorPair in ancestors(true ).zip(otherNode.ancestors(true ))) {
50
+ ancestors1.add(ancestorPair.first)
51
+ ancestors2.add(ancestorPair.second)
52
+ if (ancestors1.contains(ancestorPair.second)) return ancestorPair.second
53
+ if (ancestors2.contains(ancestorPair.first)) return ancestorPair.first
42
54
}
55
+ return null
56
+ }
57
+
58
+ data class SpecializedNonExistingNode (val node : INonExistingNode , val subConcept : IConcept ): INonExistingNode {
59
+ override fun getParent (): INonExistingNode ? = node.getParent()
60
+
61
+ override fun getContainmentLink (): IChildLink ? = node.getContainmentLink()
62
+
63
+ override fun index (): Int = node.index()
43
64
44
65
override fun replaceNode (subConcept : IConcept ? ): INode {
45
66
return node.replaceNode(coerceOutputConcept(subConcept))
@@ -81,6 +102,10 @@ fun INonExistingNode.coerceOutputConcept(subConcept: IConcept?): IConcept? {
81
102
data class ExistingNode (val node : INode ) : INonExistingNode {
82
103
override fun getParent (): INonExistingNode ? = node.parent?.let { ExistingNode (it) }
83
104
105
+ override fun getContainmentLink () = node.getContainmentLink()
106
+
107
+ override fun index () = node.index()
108
+
84
109
override fun replaceNode (subConcept : IConcept ? ): INode {
85
110
val parent = node.parent ? : throw RuntimeException (" cannot replace the root node" )
86
111
val newNode = parent.addNewChild(node.roleInParent, node.index(), coerceOutputConcept(subConcept))
@@ -109,9 +134,13 @@ data class ExistingNode(val node: INode) : INonExistingNode {
109
134
110
135
fun INode.toNonExisting () = ExistingNode (this )
111
136
112
- data class NonExistingChild (private val parent : INonExistingNode , val link : IChildLink , val index : Int = 0 ) : INonExistingNode {
137
+ data class NonExistingChild (private val parent : INonExistingNode , val link : IChildLink , private val index : Int = 0 ) : INonExistingNode {
113
138
override fun getParent () = parent
114
139
140
+ override fun getContainmentLink () = link
141
+
142
+ override fun index (): Int = index
143
+
115
144
override fun replaceNode (subConcept : IConcept ? ): INode {
116
145
val parentNode = parent.getOrCreateNode(null )
117
146
val existing = parentNode.getChildren(link).toList().getOrNull(index)
0 commit comments