How-To use the model-client v2 (Kotlin)

In order to use the client, you will need a running model-server to connect to.

Gradle Dependency

To use the model-client v2 you have to add the model-client library to your dependencies. Add the following to your build.gradle.kts:

repositories {
    mavenLocal {}
    maven { url = uri("https://artifacts.itemis.cloud/repository/maven-mps/") }
    // ...
}
// ...
dependencies {
    implementation("org.modelix:model-client:4.6.0")
    // ...
}

Usage

Once set up, creating an instance that loads the entire model from the server can be done like this:

val client = ModelClientV2.builder()
                          .url("http://localhost:28101/v2")
                          .build()

Nearly all operations are interfacing with a remote repository, consequently most operations in the client are suspending functions. As a result, we need to use Kotlin Coroutines to execute these functions. To initialize the client, we can call (we assume coroutine execution in all following code blocks):

// init is a suspend fun, so we use a coroutine
runBlocking(CoroutineScope(Dispatchers.Default).coroutineContext){
    client.init()
}

Afterward, we create a repository and replicate it locally into a ReplicatedModel. This data structure automatically synchronizes its content with the remote. We can consequently assume that its data is always correct and up-to-date.

// create a new repository
val myRepoId: RepositoryId = RepositoryId("myRepository")
client.initRepository(myRepoId)

// obtain the main branch created by default
val myBranchReference: BranchReference = BranchReference(repositoryId = myRepoId, branchName = RepositoryId.DEFAULT_BRANCH)

// replicate the branch content
val replicatedModel: ReplicatedModel = client.getReplicatedModel(myBranchReference)
// start the continuous replication
replicatedModel.start()

To ensure that read and write are executed correctly, we need to use read and write transactions whenever we interact with the content, e.g. by adding a new child:

// initial root node after repository initialization has the id 1
val rootNode: INode = replicatedModel.getBranch().getRootNode()

// to create a node we need run a write transaction
replicatedModel.getBranch().runWrite {
    val newChild: INode = rootNode.addNewChild("myRole")
    println("Added node $newChild under parent ${newChild.parent}")
}

// to get model content we need a read transaction
replicatedModel.getBranch().runRead {
    println("All nodes in repository: ${(rootNode.getDescendants(true).toMutableList())}")
}

Which will yield the following output:

Added node PNode2100000001 under parent PNode1
All nodes in repository: [PNode1, PNode2100000001]
If you try to access a node that does not exist, an exception is thrown.

Browsing to the model-sever content explorer over at http://localhost:28101/repos and selecting Explore Latest Version for myRepository you should see this:

Result in `model-server` of the above code

For more information how to deal with INodes and the client, check the model API and the ModelClientV2 API respectively.