Skip to content

Commit

Permalink
Merge pull request #66 from kairos-fhir/ctcue-questionnaires
Browse files Browse the repository at this point in the history
added two example scripts for export of LaborMethods as Questionnaire…
  • Loading branch information
kairosjonas authored Jun 21, 2024
2 parents 353ef03 + 6b26bdf commit 4341166
Show file tree
Hide file tree
Showing 3 changed files with 237 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.compiler.level>1.8</java.compiler.level>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<kairos-fhir-dsl.version>1.32.0</kairos-fhir-dsl.version>
<kairos-fhir-dsl.version>1.34.0-SNAPSHOT</kairos-fhir-dsl.version>
<junit-jupiter.version>5.8.2</junit-jupiter.version>
<maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
<gmavenplus-plugin.version>1.9.1</gmavenplus-plugin.version>
Expand Down
56 changes: 56 additions & 0 deletions src/main/groovy/projects/cxx/ctcue/questionnaire.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package projects.cxx.ctcue

import de.kairos.fhir.centraxx.metamodel.CrfTemplateField
import de.kairos.fhir.centraxx.metamodel.CrfTemplateSection
import de.kairos.fhir.centraxx.metamodel.LaborValue
import de.kairos.fhir.centraxx.metamodel.MultilingualEntry
import de.kairos.fhir.centraxx.metamodel.enums.LaborValueDType
import org.hl7.fhir.r4.model.Questionnaire

import static de.kairos.fhir.centraxx.metamodel.RootEntities.laborMethod

/**
* transforms a CXX LaborMethod to a Questionnaire.
*/
questionnaire {

id = "Questionnaire/" + context.source[laborMethod().id()]

identifier {
value = context.source[laborMethod().code()]
}

// using first section only
final def firstSection = context.source[laborMethod().crfTemplate().sections()].find()

firstSection[CrfTemplateSection.FIELDS].each { final def field ->
item {
setLinkId(field[CrfTemplateField.LABOR_VALUE][LaborValue.CODE] as String)

// assuming the question is stored as description
setText(field[CrfTemplateField.LABOR_VALUE][LaborValue.DESC_MULTILINGUAL_ENTRIES].find { it[MultilingualEntry.LANG] == "en" }[MultilingualEntry.VALUE] as String)
setType(mapToType(field[CrfTemplateField.LABOR_VALUE][LaborValue.D_TYPE] as LaborValueDType))
}
}

}

// more possible, focusing on main types
static mapToType(final LaborValueDType laborValueDType) {
switch (laborValueDType) {
case LaborValueDType.BOOLEAN:
return Questionnaire.QuestionnaireItemType.BOOLEAN
case LaborValueDType.INTEGER:
return Questionnaire.QuestionnaireItemType.INTEGER
case LaborValueDType.DECIMAL:
return Questionnaire.QuestionnaireItemType.QUANTITY
case LaborValueDType.DATE || LaborValueDType.LONGDATE:
return Questionnaire.QuestionnaireItemType.DATETIME
case LaborValueDType.TIME:
return Questionnaire.QuestionnaireItemType.TIME
case LaborValueDType.CATALOG:
return Questionnaire.QuestionnaireItemType.CHOICE
case LaborValueDType.STRING || LaborValueDType.LONGSTRING:
return Questionnaire.QuestionnaireItemType.TEXT
}
}
180 changes: 180 additions & 0 deletions src/main/groovy/projects/cxx/ctcue/questionnaireResponse.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package projects.cxx.ctcue

import de.kairos.fhir.centraxx.metamodel.AbstractCatalog
import de.kairos.fhir.centraxx.metamodel.CatalogEntry
import de.kairos.fhir.centraxx.metamodel.CrfTemplateField
import de.kairos.fhir.centraxx.metamodel.IcdEntry
import de.kairos.fhir.centraxx.metamodel.LaborFindingLaborValue
import de.kairos.fhir.centraxx.metamodel.LaborValue
import de.kairos.fhir.centraxx.metamodel.LaborValueNumeric
import de.kairos.fhir.centraxx.metamodel.PrecisionDate
import de.kairos.fhir.centraxx.metamodel.enums.LaborValueDType
import org.hl7.fhir.r4.model.QuestionnaireResponse

import static de.kairos.fhir.centraxx.metamodel.AbstractCode.CODE
import static de.kairos.fhir.centraxx.metamodel.AbstractCodeName.NAME_MULTILINGUAL_ENTRIES
import static de.kairos.fhir.centraxx.metamodel.MultilingualEntry.LANG
import static de.kairos.fhir.centraxx.metamodel.MultilingualEntry.VALUE
import static de.kairos.fhir.centraxx.metamodel.RootEntities.laborMapping

questionnaireResponse {
id = "QuestionnaireResponse/" + context.source[laborMapping().laborFinding().id()]

identifier {
value = context.source[laborMapping().laborFinding().shortName()]
}

setQuestionnaire("Questionnaire/" + context.source[laborMapping().laborFinding().laborMethod().id()])

// static, could be mapped as a param within the LaborFinding
status = QuestionnaireResponse.QuestionnaireResponseStatus.INPROGRESS

subject {
reference = "Patient/" + context.source[laborMapping().relatedPatient().id()]
}

setAuthored(context.source[laborMapping().laborFinding().findingDate()])

// author (OrgUnit or Practitioner) has to be coded within the LaborFinding

context.source[laborMapping().laborFinding().laborFindingLaborValues()].each { final def lflv ->

final def laborValue = lflv[LaborFindingLaborValue.CRF_TEMPLATE_FIELD][CrfTemplateField.LABOR_VALUE]
item {
setLinkId(laborValue[CODE] as String)

// assuming the question is stored as description
setText(laborValue[LaborValue.DESC_MULTILINGUAL_ENTRIES].find { it[LANG] == "en" }[VALUE] as String)

if (isNumeric(laborValue)) {
answer {
valueQuantity {
value = lflv[LaborFindingLaborValue.NUMERIC_VALUE]
unit = laborValue?.getAt(LaborValueNumeric.UNIT)?.getAt(CODE) as String
}
}
} else if (isBoolean(laborValue)) {
answer {
setValueBoolean(lflv[LaborFindingLaborValue.BOOLEAN_VALUE] as Boolean)
}
} else if (isDate(laborValue)) {
answer {
valueDateTime {
date = lflv[LaborFindingLaborValue.DATE_VALUE]?.getAt(PrecisionDate.DATE)
}
}
} else if (isTime(laborValue)) {
answer {
setValueTime(lflv[LaborFindingLaborValue.TIME_VALUE] as String)
}
} else if (isString(laborValue)) {
answer {
setValueString(lflv[LaborFindingLaborValue.STRING_VALUE] as String)
}
} else if (isEnumeration(laborValue)) {
valueCodeableConcept {
lflv[LaborFindingLaborValue.MULTI_VALUE].each { final entry ->
answer {
valueCoding {
system = "urn:centraxx:CodeSystem/UsageEntry"
code = entry[CODE] as String
display = entry[NAME_MULTILINGUAL_ENTRIES]?.find { it[LANG] == "en" }?.getAt(VALUE) as String
}
}
}
lflv[LaborFindingLaborValue.CATALOG_ENTRY_VALUE].each { final entry ->
answer {
valueCoding {
system = "urn:centraxx:CodeSystem/ValueList-" + entry[CatalogEntry.CATALOG]?.getAt(AbstractCatalog.ID)
code = entry[CODE] as String
display = entry[NAME_MULTILINGUAL_ENTRIES]?.find { it[LANG] == "en" }?.getAt(VALUE) as String
}
}
}
}
} else if (isOptionGroup(laborValue)) {
valueCodeableConcept {
lflv[LaborFindingLaborValue.MULTI_VALUE].each { final entry ->
answer {
valueCoding {
system = "urn:centraxx:CodeSystem/UsageEntry"
code = entry[CODE] as String
display = entry[NAME_MULTILINGUAL_ENTRIES]?.find { it[LANG] == "en" }?.getAt(VALUE) as String
}
}
}
lflv[LaborFindingLaborValue.CATALOG_ENTRY_VALUE].each { final entry ->
answer {
valueCoding {
system = "urn:centraxx:CodeSystem/ValueList-" + entry[CatalogEntry.CATALOG]?.getAt(AbstractCatalog.ID)
code = entry[CODE] as String
display = entry[NAME_MULTILINGUAL_ENTRIES]?.find { it[LANG] == "en" }?.getAt(VALUE) as String
}
}
}
}
} else if (isCatalog(laborValue)) {
valueCodeableConcept {
lflv[LaborFindingLaborValue.CATALOG_ENTRY_VALUE].each { final entry ->
answer {
valueCoding {
system = "urn:centraxx:CodeSystem/ValueList-" + entry[CatalogEntry.CATALOG]?.getAt(AbstractCatalog.ID)
code = entry[CODE] as String
display = entry[NAME_MULTILINGUAL_ENTRIES]?.find { it[LANG] == "en" }?.getAt(VALUE) as String
}
}
}
lflv[LaborFindingLaborValue.ICD_ENTRY_VALUE].each { final entry ->
answer {
valueCoding {
system = "urn:centraxx:CodeSystem/IcdCatalog-" + entry[IcdEntry.CATALOGUE]?.getAt(AbstractCatalog.ID)
code = entry[CODE] as String
display = entry[IcdEntry.PREFERRED_LONG] as String
}
}
}
}
} else {
final String msg = laborValue?.getAt(LaborValue.D_TYPE) + " not implemented yet."
System.out.println(msg)
}
}
}

}

static boolean isDTypeOf(final Object laborValue, final List<LaborValueDType> types) {
return types.contains(laborValue?.getAt(LaborValue.D_TYPE) as LaborValueDType)
}

static boolean isBoolean(final Object laborValue) {
return isDTypeOf(laborValue, [LaborValueDType.BOOLEAN])
}

static boolean isNumeric(final Object laborValue) {
return isDTypeOf(laborValue, [LaborValueDType.INTEGER, LaborValueDType.DECIMAL, LaborValueDType.SLIDER])
}

static boolean isDate(final Object laborValue) {
return isDTypeOf(laborValue, [LaborValueDType.DATE, LaborValueDType.LONGDATE])
}

static boolean isTime(final Object laborValue) {
return isDTypeOf(laborValue, [LaborValueDType.TIME])
}

static boolean isEnumeration(final Object laborValue) {
return isDTypeOf(laborValue, [LaborValueDType.ENUMERATION])
}

static boolean isString(final Object laborValue) {
return isDTypeOf(laborValue, [LaborValueDType.STRING, LaborValueDType.LONGSTRING])
}

static boolean isCatalog(final Object laborValue) {
return isDTypeOf(laborValue, [LaborValueDType.CATALOG])
}

static boolean isOptionGroup(final Object laborValue) {
return isDTypeOf(laborValue, [LaborValueDType.OPTIONGROUP])
}

0 comments on commit 4341166

Please sign in to comment.