diff --git a/pom.xml b/pom.xml
index 7a9d260b..bef3102b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
UTF-8
1.8
3.11.0
- 1.32.0
+ 1.34.0-SNAPSHOT
5.8.2
3.1.2
1.9.1
diff --git a/src/main/groovy/projects/cxx/ctcue/questionnaire.groovy b/src/main/groovy/projects/cxx/ctcue/questionnaire.groovy
new file mode 100644
index 00000000..fe63afe7
--- /dev/null
+++ b/src/main/groovy/projects/cxx/ctcue/questionnaire.groovy
@@ -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
+ }
+}
diff --git a/src/main/groovy/projects/cxx/ctcue/questionnaireResponse.groovy b/src/main/groovy/projects/cxx/ctcue/questionnaireResponse.groovy
new file mode 100644
index 00000000..7a7a34f4
--- /dev/null
+++ b/src/main/groovy/projects/cxx/ctcue/questionnaireResponse.groovy
@@ -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 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])
+}
\ No newline at end of file