|
15 | 15 |
|
16 | 16 | package org.modelix.model.api
|
17 | 17 |
|
| 18 | +import kotlinx.coroutines.flow.Flow |
| 19 | +import kotlinx.coroutines.flow.map |
| 20 | +import kotlinx.coroutines.flow.mapNotNull |
18 | 21 | import org.modelix.model.area.ContextArea
|
19 | 22 | import org.modelix.model.area.IArea
|
20 | 23 | import org.modelix.model.area.PArea
|
| 24 | +import kotlin.coroutines.coroutineContext |
21 | 25 |
|
22 | 26 | open class PNodeAdapter(val nodeId: Long, val branch: IBranch) : INode, INodeEx {
|
23 | 27 |
|
24 | 28 | init {
|
25 | 29 | require(nodeId != 0L, { "Invalid node 0" })
|
26 | 30 | }
|
27 | 31 |
|
| 32 | + private fun getTree(): ITree = branch.transaction.tree |
| 33 | + |
28 | 34 | override fun getArea(): PArea = PArea(branch)
|
29 | 35 |
|
30 | 36 | protected fun unwrap(node: INode?): Long {
|
@@ -111,12 +117,27 @@ open class PNodeAdapter(val nodeId: Long, val branch: IBranch) : INode, INodeEx
|
111 | 117 | override fun getReferenceTarget(role: String): INode? {
|
112 | 118 | notifyAccess()
|
113 | 119 | val targetRef = getReferenceTargetRef(role) ?: return null
|
114 |
| - if (targetRef is PNodeReference) { |
115 |
| - return targetRef.resolveNode(PArea(branch)) |
| 120 | + return tryResolveNodeRef(targetRef) |
| 121 | + } |
| 122 | + |
| 123 | + private fun tryResolveNodeRef(targetRef: INodeReference): INode? { |
| 124 | + return if (targetRef is PNodeReference) { |
| 125 | + targetRef.resolveIn(PArea(branch)!!) |
| 126 | + } else { |
| 127 | + val area = ContextArea.CONTEXT_VALUE.getValue() |
| 128 | + ?: throw RuntimeException(IArea::class.simpleName + " not available") |
| 129 | + targetRef.resolveIn(area!!) |
116 | 130 | }
|
117 |
| - val area = ContextArea.CONTEXT_VALUE.getValue() |
118 |
| - ?: throw RuntimeException(IArea::class.simpleName + " not available") |
119 |
| - return targetRef.resolveNode(area) |
| 131 | + } |
| 132 | + |
| 133 | + private suspend fun resolveNodeRefInCoroutine(targetRef: INodeReference): INode { |
| 134 | + return if (targetRef is PNodeReference) { |
| 135 | + targetRef.resolveIn(PArea(branch)!!) |
| 136 | + } else { |
| 137 | + val scope = coroutineContext[INodeResolutionScope] |
| 138 | + ?: throw IllegalStateException("INodeResolutionScope not set") |
| 139 | + targetRef.resolveIn(scope) |
| 140 | + } ?: throw RuntimeException("Failed to resolve node: $targetRef") |
120 | 141 | }
|
121 | 142 |
|
122 | 143 | override fun getReferenceTargetRef(role: String): INodeReference? {
|
@@ -160,6 +181,45 @@ open class PNodeAdapter(val nodeId: Long, val branch: IBranch) : INode, INodeEx
|
160 | 181 | return branch.transaction.getReferenceRoles(nodeId).toList()
|
161 | 182 | }
|
162 | 183 |
|
| 184 | + override fun getAllChildrenAsFlow(): Flow<INode> { |
| 185 | + return getTree().getAllChildrenAsFlow(nodeId).map { wrap(it)!! } |
| 186 | + } |
| 187 | + |
| 188 | + override fun getDescendantsAsFlow(includeSelf: Boolean): Flow<INode> { |
| 189 | + return getTree().getDescendantsAsFlow(nodeId, includeSelf).map { wrap(it)!! } |
| 190 | + } |
| 191 | + |
| 192 | + override fun getAllReferenceTargetsAsFlow(): Flow<Pair<IReferenceLink, INode>> { |
| 193 | + return getAllReferenceTargetRefsAsFlow().map { it.first to resolveNodeRefInCoroutine(it.second) } |
| 194 | + } |
| 195 | + |
| 196 | + override fun getAllReferenceTargetRefsAsFlow(): Flow<Pair<IReferenceLink, INodeReference>> { |
| 197 | + return getTree().getAllReferenceTargetsAsFlow(nodeId).map { this.resolveReferenceLinkOrFallback(it.first) to it.second } |
| 198 | + } |
| 199 | + |
| 200 | + override fun getChildrenAsFlow(role: IChildLink): Flow<INode> { |
| 201 | + val tree = getTree() |
| 202 | + return tree.getChildrenAsFlow(nodeId, role.key(tree)).map { wrap(it)!! } |
| 203 | + } |
| 204 | + |
| 205 | + override fun getParentAsFlow(): Flow<INode> { |
| 206 | + return getTree().getParentAsFlow(nodeId).map { wrap(it)!! } |
| 207 | + } |
| 208 | + |
| 209 | + override fun getPropertyValueAsFlow(role: IProperty): Flow<String?> { |
| 210 | + val tree = getTree() |
| 211 | + return tree.getPropertyValueAsFlow(nodeId, role.key(tree)) |
| 212 | + } |
| 213 | + |
| 214 | + override fun getReferenceTargetAsFlow(role: IReferenceLink): Flow<INode> { |
| 215 | + return getReferenceTargetRefAsFlow(role).mapNotNull { tryResolveNodeRef(it) } |
| 216 | + } |
| 217 | + |
| 218 | + override fun getReferenceTargetRefAsFlow(role: IReferenceLink): Flow<INodeReference> { |
| 219 | + val tree = getTree() |
| 220 | + return tree.getReferenceTargetAsFlow(nodeId, role.key(tree)) |
| 221 | + } |
| 222 | + |
163 | 223 | override fun equals(o: Any?): Boolean {
|
164 | 224 | if (this === o) {
|
165 | 225 | return true
|
|
0 commit comments