mlrpc.protocol.2.0.3.source-code.Deserializer.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of protocol Show documentation
Show all versions of protocol Show documentation
xml-rpc implementation written in Kotlin
The newest version!
/*
* Copyright (c) 2022 Andreas Scheja. Use of this source code is governed by the Apache 2.0 license.
*/
package org.ascheja.xmlrpc.protocol
import org.w3c.dom.Element
internal class Deserializer internal constructor() {
companion object {
private fun Element.associateChildren(): Map = buildMap {
for (i in 0 until childNodes.length) {
val child = childNodes.item(i) as? Element ?: continue
put(child.tagName, child)
}
}
private fun Element.mapChildren(block: (Element) -> T): List = buildList {
for (i in 0 until childNodes.length) {
val child = childNodes.item(i) as? Element ?: continue
add(block(child))
}
}
}
internal fun parseMethodCall(methodCallElement: Element): MethodCall {
if (methodCallElement.tagName != "methodCall") error("not a method call")
val children = methodCallElement.associateChildren()
return MethodCall(
children["methodName"]?.textContent ?: error("missing methodName"),
children["params"]?.mapChildren { paramElement ->
if (paramElement.tagName != "param") error("expecting , got <${paramElement.tagName}>")
parseValue(paramElement.associateChildren()["value"] ?: error(" missing a "))
} ?: emptyList()
)
}
internal fun parseMethodResponse(methodResponseElement: Element): MethodResponse {
if (methodResponseElement.tagName != "methodResponse") error("not a method response")
val children = methodResponseElement.associateChildren()
if (children.size != 1) error(" with invalid size: ${children.size}")
val (tagName, element) = children.entries.first()
return when (tagName) {
"fault" -> {
val faultStruct = parseValue(
element.associateChildren()["value"] ?: error("missing in ")
) as? StructValue ?: error("expected 's to be a ")
MethodResponseFault(
(faultStruct.members["faultCode"] as? IntegerValue)?.value ?: error("missing faultCode in "),
(faultStruct.members["faultString"] as? StringValue)?.value ?: error("missing faultString in ")
)
}
"params" -> {
MethodResponseSuccess(
element.mapChildren { paramElement ->
if (paramElement.tagName != "param") error("expecting , got <${paramElement.tagName}>")
parseValue(paramElement.associateChildren()["value"] ?: error(" missing a "))
}
)
}
else -> error("unexpected <$tagName> in ")
}
}
internal fun parseValue(valueElement: Element): Value {
val children = valueElement.associateChildren()
if (children.size != 1) error(" with invalid size: ${children.size}")
val (tagName, element) = children.entries.first()
return when (tagName) {
"i4", "int" -> IntegerValue(element.textContent.toInt())
"string" -> StringValue(element.textContent)
"boolean" -> BooleanValue(element.textContent.toInt() == 1)
"double" -> DoubleValue(element.textContent.toDouble())
"datetime.iso8601" -> DateTimeIso8601Value(element.textContent)
"base64" -> Base64Value(element.textContent)
"struct" -> StructValue(
element.mapChildren { memberElement ->
val memberChildren = memberElement.associateChildren()
Pair(
memberChildren["name"]?.textContent ?: error(" missing "),
parseValue(memberChildren["value"] ?: error(" missing "))
)
}.toMap()
)
"array" -> {
val dataElement = element.associateChildren()["data"] ?: error("missing element in ")
ArrayValue(dataElement.mapChildren(::parseValue))
}
else -> error("unknown value type <$tagName>")
}
}
}