-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement /convert endpoint for xml/json conversion (#165)
- Loading branch information
1 parent
0fe78c5
commit 45a0ca0
Showing
12 changed files
with
520 additions
and
12 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
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
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
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
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
6 changes: 6 additions & 0 deletions
6
src/jvmMain/kotlin/controller/conversion/ConversionController.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 |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package controller.conversion | ||
|
||
interface ConversionController { | ||
suspend fun convertRequest(content: String, type: String? = "json", version: String? = "5.0", toType: String? = type, | ||
toVersion: String? = version): String | ||
} |
44 changes: 44 additions & 0 deletions
44
src/jvmMain/kotlin/controller/conversion/ConversionControllerImpl.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 |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package controller.conversion | ||
|
||
import controller.validation.ValidationServiceFactory | ||
import model.CliContext | ||
import org.hl7.fhir.validation.ValidationEngine | ||
import org.koin.core.component.KoinComponent | ||
import org.koin.core.component.inject | ||
import java.nio.file.Files | ||
import java.nio.file.Path | ||
import kotlin.io.path.deleteIfExists | ||
|
||
class ConversionControllerImpl : ConversionController, KoinComponent { | ||
|
||
private val validationServiceFactory by inject<ValidationServiceFactory>() | ||
|
||
override suspend fun convertRequest(content: String, type: String?, version: String?, toType: String?, | ||
toVersion: String?): String { | ||
val fromType = type ?: "json" | ||
val fromVersion = version ?: "5.0" | ||
|
||
val cliContext = CliContext() | ||
cliContext.sv = fromVersion | ||
cliContext.targetVer = toVersion ?: fromVersion | ||
|
||
var validator: ValidationEngine? = validationServiceFactory.getValidationEngine(cliContext) | ||
|
||
var input: Path? = null | ||
var output: Path? = null | ||
try { | ||
input = Files.createTempFile("input", ".$fromType") | ||
Files.writeString(input.toAbsolutePath(), content) | ||
cliContext.addSource(input.toAbsolutePath().toString()) | ||
|
||
output = Files.createTempFile("convert", ".${toType ?: fromType}") | ||
cliContext.output = output.toAbsolutePath().toString() | ||
|
||
validationServiceFactory.getValidationService().convertSources(cliContext, validator) | ||
return Files.readString(output.toAbsolutePath()) | ||
} finally { | ||
input?.deleteIfExists() | ||
output?.deleteIfExists() | ||
} | ||
} | ||
} |
83 changes: 83 additions & 0 deletions
83
src/jvmMain/kotlin/controller/conversion/ConversionModule.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 |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package controller.conversion | ||
|
||
import constants.CONVERSION_ENDPOINT | ||
|
||
import io.ktor.http.* | ||
import io.ktor.server.application.* | ||
import io.ktor.server.request.* | ||
import io.ktor.server.response.* | ||
import io.ktor.server.routing.* | ||
import org.koin.ktor.ext.inject | ||
|
||
const val NO_CONTENT_PROVIDED_MESSAGE = "No content for conversion provided in request." | ||
const val INVALID_TYPE_MESSAGE = "Invalid type parameter! Supported xml or json." | ||
const val INVALID_TO_TYPE_MESSAGE = "Invalid toType parameter! Supported xml or json." | ||
|
||
fun Route.conversionModule() { | ||
|
||
val conversionController by inject<ConversionController>() | ||
|
||
post(CONVERSION_ENDPOINT) { | ||
val fhirJson = ContentType("application", "fhir+json") | ||
val fhirXml = ContentType("application", "fhir+xml") | ||
|
||
val logger = call.application.environment.log | ||
val content = call.receiveText() | ||
val type = call.request.queryParameters["type"]?.lowercase() ?: when { | ||
call.request.contentType() == ContentType.Application.Json -> "json" | ||
call.request.contentType() == ContentType.Application.Xml -> "xml" | ||
call.request.contentType().withoutParameters() == fhirJson -> "json" | ||
call.request.contentType().withoutParameters() == fhirXml -> "xml" | ||
else -> call.request.contentType().contentSubtype | ||
} | ||
val version = call.request.queryParameters["version"] ?: | ||
call.request.contentType().parameter("fhirVersion") ?: "5.0" | ||
|
||
|
||
val acceptContentType = if(call.request.accept() != null) | ||
ContentType.parse(call.request.accept().toString()) else null | ||
|
||
val toType = call.request.queryParameters["toType"]?.lowercase() ?: when { | ||
acceptContentType == ContentType.Application.Json -> "json" | ||
acceptContentType == ContentType.Application.Xml -> "xml" | ||
acceptContentType?.withoutParameters() == fhirJson -> "json" | ||
acceptContentType?.withoutParameters() == fhirXml -> "xml" | ||
call.request.accept() != null -> acceptContentType?.contentSubtype | ||
else -> type | ||
} | ||
val toVersion = call.request.queryParameters["toVersion"] ?: | ||
acceptContentType?.parameter("fhirVersion") ?: version | ||
|
||
logger.info("Received Conversion Request. Convert to $toVersion FHIR version and $toType type. " + | ||
"Memory (free/max): ${java.lang.Runtime.getRuntime().freeMemory()}/" + | ||
"${java.lang.Runtime.getRuntime().maxMemory()}") | ||
|
||
when { | ||
content.isEmpty() -> { | ||
call.respond(HttpStatusCode.BadRequest, NO_CONTENT_PROVIDED_MESSAGE) | ||
} | ||
type != "xml" && type != "json" -> { | ||
call.respond(HttpStatusCode.BadRequest, INVALID_TYPE_MESSAGE) | ||
} | ||
toType != "xml" && toType != "json" -> { | ||
call.respond(HttpStatusCode.BadRequest, INVALID_TO_TYPE_MESSAGE) | ||
} | ||
|
||
else -> { | ||
try { | ||
val response = conversionController.convertRequest(content, type, version, toType, | ||
toVersion) | ||
val contentType = when { | ||
toType == "xml" -> fhirXml.withParameter("fhirVersion", toVersion) | ||
toType == "json" -> fhirJson.withParameter("fhirVersion", toVersion) | ||
else -> acceptContentType?.withParameter("fhirVersion", toVersion) | ||
} | ||
call.respondText(response, contentType, HttpStatusCode.OK) | ||
} catch (e: Exception) { | ||
logger.error(e.localizedMessage, e) | ||
call.respond(HttpStatusCode.InternalServerError, e.localizedMessage) | ||
} | ||
} | ||
} | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
src/jvmMain/kotlin/controller/validation/ValidationServiceFactory.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,8 +1,12 @@ | ||
package controller.validation | ||
|
||
import org.hl7.fhir.validation.ValidationEngine | ||
import org.hl7.fhir.validation.cli.model.CliContext | ||
import org.hl7.fhir.validation.cli.services.ValidationService | ||
|
||
interface ValidationServiceFactory { | ||
|
||
fun getValidationService() : ValidationService | ||
|
||
fun getValidationEngine(cliContext: CliContext) : ValidationEngine? | ||
} |
44 changes: 32 additions & 12 deletions
44
src/jvmMain/kotlin/controller/validation/ValidationServiceFactoryImpl.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
Oops, something went wrong.