commit e492d02140c9a35cd9ec551a5d8619831989fe47
parent f50906d1f48af0c5a5b190d06578103eaebdbe4d
Author: Marcello Stanisci <stanisci.m@gmail.com>
Date: Fri, 11 Oct 2019 13:27:53 +0200
introduce helper downcast function
Diffstat:
3 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/sandbox/src/main/kotlin/Main.kt b/sandbox/src/main/kotlin/Main.kt
@@ -39,13 +39,46 @@ import io.ktor.server.netty.Netty
import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.LoggerFactory
import org.w3c.dom.Document
+import org.w3c.dom.Element
import tech.libeufin.messages.ebics.hev.HEVResponseDataType
+import tech.libeufin.messages.ebics.keyrequest.EbicsUnsecuredRequest
+import tech.libeufin.messages.ebics.keyrequest.UnsecuredReqOrderDetailsType
import java.text.DateFormat
import javax.xml.bind.JAXBElement
val logger = LoggerFactory.getLogger("tech.libeufin.sandbox")
val xmlProcess = XML()
+/**
+ * Sometimes, JAXB is not able to figure out to which type
+ * a certain XML node should be bound to. This happens when
+ * one element name can have multiple definitions therefore
+ * JAXB renders it as a abstract class. In that case, the
+ * object factory must be instructed about the subtype to create,
+ * and this is done via injecting the xsi:type attribute to the
+ * "overloaded" XML element.
+ *
+ * Alternative methods of addressing this?
+ *
+ * @param document the XML Document to modify
+ * @param node the name of the overloaded element (ideally this
+ * parameter should be a XPATH address)
+ * @param type the type to downcast @a node to
+ * @return the modified document
+ */
+fun downcastXml(document: Document, node: String, type: String) : Document {
+
+ val x: Element = document.getElementsByTagName("OrderDetails")?.item(0) as Element
+
+ x.setAttributeNS(
+ "http://www.w3.org/2001/XMLSchema-instance",
+ "type",
+ type
+ )
+
+ return document
+}
+
private suspend fun ApplicationCall.adminCustomers() {
val body = try {
receive<CustomerRequest>()
@@ -170,6 +203,17 @@ private suspend fun ApplicationCall.ebicsweb() {
/* Manage request. */
+ val bodyJaxb = xmlProcess.convertDomToJaxb<EbicsUnsecuredRequest>(
+ "tech.libeufin.messages.ebics.keyrequest",
+ downcastXml(
+ bodyDocument,
+ "OrderDetails",
+ "UnsecuredReqOrderDetailsType"
+ )
+ )
+
+ logger.info("Serving a ${bodyJaxb.header.static.orderDetails.orderType} request")
+
respond(
HttpStatusCode.NotImplemented,
SandboxError("Not implemented")
diff --git a/sandbox/src/main/kotlin/XML.kt b/sandbox/src/main/kotlin/XML.kt
@@ -176,13 +176,13 @@ class XML {
* @param document the document to convert into JAXB.
* @return the JAXB object reflecting the original XML document.
*/
- fun convertDomToJaxb(packageName: String, document: Document): Any {
+ fun <T>convertDomToJaxb(packageName: String, document: Document) : T {
val jc = JAXBContext.newInstance(packageName)
/* Marshalling the object into the document. */
val m = jc.createUnmarshaller()
- return m.unmarshal(document) // document "went" into Jaxb
+ return m.unmarshal(document) as T // document "went" into Jaxb
}
/**
diff --git a/sandbox/src/test/kotlin/DomToJaxbTest.kt b/sandbox/src/test/kotlin/DomToJaxbTest.kt
@@ -2,6 +2,7 @@ package tech.libeufin.sandbox
import org.junit.Test
import org.w3c.dom.Element
+import tech.libeufin.messages.ebics.keyrequest.EbicsUnsecuredRequest
import tech.libeufin.messages.ebics.keyrequest.OrderDetailsType
import tech.libeufin.messages.ebics.keyrequest.UnsecuredReqOrderDetailsType
@@ -22,7 +23,7 @@ class DomToJaxbTest {
"UnsecuredReqOrderDetailsType"
)
- processor.convertDomToJaxb(
+ processor.convertDomToJaxb<EbicsUnsecuredRequest>(
"tech.libeufin.messages.ebics.keyrequest",
iniDom)
}