This repository was archived by the owner on Sep 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathIndexProjection.kt
More file actions
88 lines (71 loc) · 2.61 KB
/
Copy pathIndexProjection.kt
File metadata and controls
88 lines (71 loc) · 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package dev.arkbuilders.arklib.data.index
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.mapNotNull
import dev.arkbuilders.arklib.ResourceId
import java.nio.file.Path
/**
* [ResourcePredicate] allows us to define [IndexProjection]
* in the most generic way. */
typealias ResourcePredicate = (Resource, Path) -> Boolean
/**
* [IndexProjection] is a type of index that returns ids
* only for matching resources. Matching can be made
* either by path or by id.
*
* Use-cases:
* 1. "favorite" folder, which is a subfolder of a "root folder",
* can be implemented as [IndexProjection] matching specific
* paths.
* 2. various filters by size or resource kind could be
* implemented as [IndexProjection] matching specific
* values of `Resource` fields.
*/
class IndexProjection(
private val root: RootIndex,
private val predicate: ResourcePredicate): ResourceIndex {
override val roots: Set<RootIndex> = setOf(root)
override val updates: Flow<ResourceUpdates> = root.updates
.mapNotNull { updates ->
val deleted = updates.deleted.filterValues { lost ->
predicate(lost.resource, lost.path)
}
val added = updates.added.filterValues { new ->
predicate(new.resource, new.path)
}
if (deleted.isEmpty() && added.isEmpty()) {
return@mapNotNull null
}
ResourceUpdates(deleted, added)
}
override suspend fun updateAll() = root.updateAll()
override suspend fun updateOne(resourcePath: Path, oldId: ResourceId) =
root.updateOne(resourcePath, oldId)
override fun allResources(): Map<ResourceId, Resource> {
val allPathsMap = root.allPaths()
return root
.allResources()
.filter { (id, res) -> predicate(res, allPathsMap[id]!!) }
}
override fun getResource(id: ResourceId): Resource? {
val result = getResourceAndPath(id)
return result?.first
}
override fun allPaths(): Map<ResourceId, Path> {
val allResourcesMap = root.allResources()
return root
.allPaths()
.filter { (id, path) -> predicate(allResourcesMap[id]!!, path) }
}
override fun getPath(id: ResourceId): Path? {
val result = getResourceAndPath(id)
return result?.second
}
private fun getResourceAndPath(id: ResourceId): Pair<Resource, Path>? {
val path = root.getPath(id)
val resource = root.getResource(id)
if (path == null || resource == null) {
return null
}
return resource to path
}
}