Skip to content

Commit

Permalink
Merge pull request #66 from modelix/advanced-model-server-api
Browse files Browse the repository at this point in the history
MODELIX-54 Higher level API for the advanced-model-client
  • Loading branch information
slisson authored Mar 24, 2023
2 parents 7e20eee + 6930990 commit 76781e2
Show file tree
Hide file tree
Showing 51 changed files with 1,823 additions and 442 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,17 @@ import io.ktor.client.request.*
import io.ktor.server.application.*
import io.ktor.server.testing.*
import io.ktor.websocket.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ClosedReceiveChannelException
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import org.modelix.authorization.installAuthentication
import org.modelix.model.api.addNewChild
import org.modelix.model.api.getDescendants
import org.modelix.model.server.InMemoryStoreClient
import org.modelix.model.server.JsonModelServer
import org.modelix.model.server.JsonModelServer2
import org.modelix.model.server.LocalModelClient
import org.modelix.model.server.api.MessageFromClient
import org.modelix.model.server.api.MessageFromServer
import org.modelix.model.server.store.InMemoryStoreClient
import org.modelix.model.server.handlers.DeprecatedLightModelServer
import org.modelix.model.server.handlers.LightModelServer
import org.modelix.model.server.store.LocalModelClient
import org.modelix.model.test.RandomModelChangeGenerator
import kotlin.random.Random
import kotlin.test.Ignore
Expand All @@ -54,8 +48,8 @@ class LightModelClientTest {
install(io.ktor.server.websocket.WebSockets)
val modelClient = LocalModelClient(InMemoryStoreClient())
localModelClient = modelClient
JsonModelServer(modelClient).init(this)
JsonModelServer2(modelClient).init(this)
DeprecatedLightModelServer(modelClient).init(this)
LightModelServer(modelClient).init(this)
}
val client = createClient {
install(WebSockets)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ open class PNodeAdapter(val nodeId: Long, val branch: IBranch) : INode {
}

override fun getReferenceRoles(): List<String> {
return branch.transaction.getPropertyRoles(nodeId).toList()
return branch.transaction.getReferenceRoles(nodeId).toList()
}

override fun equals(o: Any?): Boolean {
Expand Down Expand Up @@ -205,3 +205,6 @@ open class PNodeAdapter(val nodeId: Long, val branch: IBranch) : INode {
notifyAccess()
}
}

fun IBranch.getNode(id: Long): INode = PNodeAdapter(id, this)
fun IBranch.getRootNode(): INode = getNode(ITree.ROOT_ID)
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,16 @@ fun NodeData.uid(model: ModelData): String {
(id ?: throw IllegalArgumentException("Node has no ID"))
}
fun ModelData.nodeUID(node: NodeData): String = node.uid(this)

fun INode.asData(): NodeData = NodeData(
id = reference.serialize(),
concept = concept?.getUID(),
role = roleInParent,
properties = getPropertyRoles().associateWithNotNull { getPropertyValue(it) },
references = getReferenceRoles().associateWithNotNull { getReferenceTargetRef(it)?.serialize() },
children = allChildren.map { it.asData() }
)

public inline fun <K, V : Any> Iterable<K>.associateWithNotNull(valueSelector: (K) -> V?): Map<K, V> {
return associateWith { valueSelector(it) }.filterValues { it != null } as Map<K, V>
}
6 changes: 6 additions & 0 deletions model-client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ tasks.named("check") {
val kotlinCoroutinesVersion: String by rootProject
val kotlinLoggingVersion: String by rootProject
val ktorVersion: String by rootProject
val kotlinxSerializationVersion: String by rootProject

kotlin {
jvm()
Expand All @@ -51,11 +52,16 @@ kotlin {
val commonMain by getting {
dependencies {
api(project(":model-api"))
implementation(project(":model-server-api"))
kotlin("stdlib-common")
implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.4")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion")
implementation("io.github.microutils:kotlin-logging:$kotlinLoggingVersion")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
}
}
val commonTest by getting {
Expand Down
21 changes: 21 additions & 0 deletions model-client/src/commonMain/kotlin/org/modelix/model/IVersion.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modelix.model

import org.modelix.model.api.ITree

interface IVersion {
fun getShaHash(): String
fun getTree(): ITree
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modelix.model.client2

import org.modelix.model.IVersion
import org.modelix.model.api.IIdGenerator
import org.modelix.model.lazy.BranchReference
import org.modelix.model.lazy.RepositoryId
import org.modelix.model.server.api.ModelQuery

interface IModelClientV2 {
fun getClientId(): Int
fun getIdGenerator(): IIdGenerator
fun getUserId(): String?

suspend fun initRepository(repository: RepositoryId): IVersion
suspend fun listRepositories(): List<RepositoryId>

suspend fun listBranches(repository: RepositoryId): List<BranchReference>

suspend fun loadVersion(versionHash: String, baseVersion: IVersion?): IVersion

/**
* The pushed version is merged automatically by the server with the current head.
* The merge result is returned.
*/
suspend fun push(branch: BranchReference, version: IVersion): IVersion

suspend fun pull(branch: BranchReference, lastKnownVersion: IVersion?): IVersion
suspend fun pull(branch: BranchReference, lastKnownVersion: IVersion?, filter: ModelQuery): IVersion

suspend fun poll(branch: BranchReference, lastKnownVersion: IVersion?): IVersion
suspend fun poll(branch: BranchReference, lastKnownVersion: IVersion?, filter: ModelQuery): IVersion
}
Loading

0 comments on commit 76781e2

Please sign in to comment.