Skip to content

Commit

Permalink
TreeBuilder 2.0. Declarative building with Kotlin DSL.
Browse files Browse the repository at this point in the history
Add more methods, fix inconsistencies and bugs, improve logic, docs. Adjust examples.

Adjust project structure and move examples to test sources.
  • Loading branch information
lifestreamy committed Dec 17, 2024
1 parent f483363 commit 6121814
Show file tree
Hide file tree
Showing 20 changed files with 1,353 additions and 533 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ bin/
.vscode/

### Mac OS ###
.DS_Store
.DS_Store
/.kotlin/
33 changes: 0 additions & 33 deletions build.gradle

This file was deleted.

27 changes: 27 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
plugins {
kotlin("jvm") version "2.1.0"
`java-library`
}

val jvmVer : String by project
val jvmVerInt
get() = jvmVer.toInt()


kotlin {
group = "com.github"
version = "2.0.0"

jvmToolchain(jvmVerInt)

}

tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}

dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.jetbrains.kotlin:kotlin-test")
}
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
kotlin.code.style=official
jvmVer=17
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
3 changes: 0 additions & 3 deletions settings.gradle

This file was deleted.

17 changes: 17 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}

}

dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
}
}

rootProject.name = "TreeBuilder"
94 changes: 94 additions & 0 deletions src/main/kotlin/com/github/treeBuilder/Extensions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.github.treeBuilder

import com.github.treeBuilder.dsl.NodeList

/**
* Get all leaves (nodes that have no children) from below this node.
* @return `this` node if it has no children.
*/
fun <T> TreeNode<T>.getAllLeaves(): NodeList<T> {
var leafList = listOf<TreeNode<T>>()
children.ifEmpty { return listOf(this) }.forEach { child ->
leafList = leafList + child.getAllLeaves()
}
return leafList
}

/**
* Get all children nodes below the passed node, including this node.
* @return `this` node and all its inheritors.
*/
fun <T> TreeNode<T>.getAllBelow(): NodeList<T> {
var childrenList = listOf<TreeNode<T>>()
children.forEach { child ->
childrenList = childrenList + child.getAllBelow()
}
return listOf(this) + childrenList
}

/**
* Print all nodes in a node list, each node shifted by `20 * depth`
*/
fun <T> NodeList<T>.printNodesWithDepth() {
forEach {
println(" ".repeat(20 * it.depth) + "(${it.depth}) ${it.name}")
}
}

/**
* Get String representation of a path from this node.
* @return `"Invalid Path"` if the path does not exist
*/
fun <T> TreeNode<T>.getStringPath(vararg path: Int): String {
return if (isValidPath(*path)) {
var currentNode = this
var s = currentNode.name
for (element in path) {
currentNode = currentNode.children[element]
s += " -> ${currentNode.name}"
}
s
} else "Invalid Path"
}

/**
* Get String representation of a path from the tree root.
* @return `"Invalid Path"` if the path does not exist
*/
fun <T> Tree<T>.getStringPath(vararg path: Int): String = root.getStringPath(*path)

/**
* Get a [String] representation of the path from the tree root to this node.
* @return `"Invalid Path"` if the path does not exist
*/
fun <T> TreeNode<T>.getStringPathFromRoot(): String {
val pathFromRoot = this.getPath().toIntArray()
return treeRef.getStringPath(*pathFromRoot)
}

/**
* Prints out all leaves, each shifted by `20 * depth`
*/
fun <T> Tree<T>.printLeavesWithDepth() {
val allLeafNodes = getAllLeaves().asReversed() // Looks better reversed for some reason
println("All leaf nodes (amount = ${allLeafNodes.size}) are:")
allLeafNodes.printNodesWithDepth()
}

/**
* Get a visualization of the whole tree.
*
* How to read the visualization:
* All nodes with depth
* `(x) == (x + 1)` of a node to the left
* and below that node are its children
*/
fun <T> Tree<T>.visualizeTree() {
getAllNodes().run {
println("Visualizing a tree:" +
"\n$this" +
"\nTree name = \"$treeName\"")
println("All nodes (amount = ${size}) are:")
printNodesWithDepth()
}
}
27 changes: 27 additions & 0 deletions src/main/kotlin/com/github/treeBuilder/Path.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.github.treeBuilder

/** An immutable representation of a path, supporting convenient concatenation
* Todo not used right now
* */
@ConsistentCopyVisibility
data class Path internal constructor(val path: IntArray) {
companion object {
val ROOT: Path = Path(intArrayOf())
}

infix operator fun plus(other: Path): Path = Path(path + other.path)

override fun equals(other: Any?): Boolean = when {
(this === other) -> true
(javaClass != other?.javaClass) -> false
else -> path.contentEquals((other as Path).path)
}

override fun hashCode(): Int = path.contentHashCode()

}

@Deprecated("Not yet useful", level = DeprecationLevel.HIDDEN)
fun path(vararg indices: Int): Path = Path(indices)

typealias IntPath = List<Int> // can use this typealias instead of List<Int> where needed
Loading

0 comments on commit 6121814

Please sign in to comment.