-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds command line property source. (#217)
* Adds command line property source. * Adds map property source and tests for map and command line. Co-authored-by: Frederic Kneier <[email protected]>
- Loading branch information
1 parent
68971ad
commit eab4d7c
Showing
3 changed files
with
162 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 54 additions & 26 deletions
80
hoplite-core/src/main/kotlin/com/sksamuel/hoplite/parsers/loadProps.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,71 @@ | ||
package com.sksamuel.hoplite.parsers | ||
|
||
import com.sksamuel.hoplite.MapNode | ||
import com.sksamuel.hoplite.Pos | ||
import com.sksamuel.hoplite.StringNode | ||
import com.sksamuel.hoplite.Node | ||
import com.sksamuel.hoplite.* | ||
import java.util.* | ||
|
||
@Suppress("UNCHECKED_CAST") | ||
fun Properties.toNode(source: String): Node { | ||
fun Properties.toNode(source: String) = asIterable().toNode( | ||
source = source, | ||
keyExtractor = { it.key.toString() }, | ||
valueExtractor = { it.value } | ||
) | ||
|
||
val valueMarker = "____value" | ||
@Suppress("UNCHECKED_CAST") | ||
fun <T : Any> Map<String, T?>.toNode(source: String) = entries.toNode( | ||
source = source, | ||
keyExtractor = { it.key }, | ||
valueExtractor = { it.value }, | ||
) | ||
|
||
data class Element( | ||
val values: MutableMap<String, Element> = hashMapOf(), | ||
var value: Any? = null, | ||
) | ||
|
||
@Suppress("UNCHECKED_CAST") | ||
private fun <T> Iterable<T>.toNode(source: String, keyExtractor: (T) -> String, valueExtractor: (T) -> Any?): Node { | ||
val map = Element() | ||
|
||
val root = mutableMapOf<String, Any>() | ||
stringPropertyNames().toList().map { key -> | ||
forEach { item -> | ||
val key = keyExtractor(item) | ||
val value = valueExtractor(item) | ||
val segments = key.split(".") | ||
|
||
val components = key.split('.') | ||
val map = components.fold(root) { acc, k -> | ||
acc.getOrPut(k) { mutableMapOf<String, Any>() } as MutableMap<String, Any> | ||
segments.foldIndexed(map) { index, element, segment -> | ||
element.values.computeIfAbsent(segment) { Element() }.also { | ||
if (index == segments.size - 1) it.value = value | ||
} | ||
} | ||
map.put(valueMarker, getProperty(key)) | ||
} | ||
|
||
val pos = Pos.FilePos(source) | ||
|
||
fun Map<String, Any>.toNode(): Node { | ||
val maps = filterValues { it is MutableMap<*, *> }.mapValues { | ||
when (val v = it.value) { | ||
is MutableMap<*, *> -> (v as MutableMap<String, Any>).toNode() | ||
else -> throw java.lang.RuntimeException("Bug: unsupported state $it") | ||
} | ||
} | ||
val value = this[valueMarker] | ||
return when { | ||
value == null && maps.isEmpty() -> MapNode(emptyMap(), pos) | ||
value == null && maps.isNotEmpty() -> MapNode(maps.toMap(), pos) | ||
maps.isEmpty() -> StringNode(value.toString(), pos) | ||
else -> MapNode(maps.toMap(), pos, StringNode(value.toString(), pos)) | ||
fun Any.transform(): Node = when (this) { | ||
is Element -> when { | ||
value != null && values.isEmpty() -> value?.transform() ?: Undefined | ||
else -> MapNode( | ||
map = values.takeUnless { it.isEmpty() }?.mapValues { it.value.transform() } ?: emptyMap(), | ||
value = value?.transform() ?: Undefined, | ||
pos = pos, | ||
) | ||
} | ||
is Array<*> -> ArrayNode( | ||
elements = mapNotNull { it?.transform() }, | ||
pos = pos, | ||
) | ||
is Collection<*> -> ArrayNode( | ||
elements = mapNotNull { it?.transform() }, | ||
pos = pos, | ||
) | ||
is Map<*, *> -> MapNode( | ||
map = takeUnless { it.isEmpty() }?.mapNotNull { entry -> | ||
entry.value?.let { entry.key.toString() to it.transform() } | ||
}?.toMap() ?: emptyMap(), | ||
pos = pos, | ||
) | ||
else -> StringNode(this.toString(), pos) | ||
} | ||
|
||
return root.toNode() | ||
val result = map.transform() | ||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters