This commit is contained in:
ShaunDonn 2021-08-05 17:34:52 -07:00
Родитель 8ed6bf03e2
Коммит 03bcbf1160
32 изменённых файлов: 390 добавлений и 399 удалений

Просмотреть файл

@ -28,17 +28,15 @@
84C0C50D26AF4FBD00FF5E35 /* SecretStoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C0C50C26AF4FBD00FF5E35 /* SecretStoreError.swift */; };
84C0C51526AF706300FF5E35 /* ViewControllerBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C0C51426AF706300FF5E35 /* ViewControllerBase.swift */; };
84C2A56326A9E6A9003F59C0 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C2A56226A9E6A9003F59C0 /* UIView.swift */; };
84CBB8A5269E005300F2D507 /* FHIRtoRK.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CBB8A4269E005300F2D507 /* FHIRtoRK.swift */; };
84CBB8B0269E007100F2D507 /* RKtoFHIR.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CBB8AF269E007100F2D507 /* RKtoFHIR.swift */; };
84D04DC826A99D7C001BA808 /* CustomTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D04DC726A99D7C001BA808 /* CustomTableViewCell.swift */; };
84CBB8A5269E005300F2D507 /* FhirToResearchKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CBB8A4269E005300F2D507 /* FhirToResearchKit.swift */; };
84CBB8B0269E007100F2D507 /* ResearchKitToFhir.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CBB8AF269E007100F2D507 /* ResearchKitToFhir.swift */; };
84D04DC826A99D7C001BA808 /* QuestionnaireListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D04DC726A99D7C001BA808 /* QuestionnaireListTableViewCell.swift */; };
84DBBCF426BB3E400007EB33 /* FhirTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DBBCF326BB3E400007EB33 /* FhirTypes.swift */; };
84EDAAB32683969D003A0AE2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EDAAB22683969D003A0AE2 /* AppDelegate.swift */; };
84EDAAB52683969D003A0AE2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EDAAB42683969D003A0AE2 /* SceneDelegate.swift */; };
84EDAAB72683969D003A0AE2 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EDAAB62683969D003A0AE2 /* ViewController.swift */; };
84EDAABA2683969D003A0AE2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84EDAAB82683969D003A0AE2 /* Main.storyboard */; };
84EDAABC268396A1003A0AE2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84EDAABB268396A1003A0AE2 /* Assets.xcassets */; };
84EDAABF268396A1003A0AE2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84EDAABD268396A1003A0AE2 /* LaunchScreen.storyboard */; };
84EDAACA268396A2003A0AE2 /* researchKitOnFhirTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EDAAC9268396A2003A0AE2 /* researchKitOnFhirTests.swift */; };
84EDAAD5268396A2003A0AE2 /* researchKitOnFhirUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EDAAD4268396A2003A0AE2 /* researchKitOnFhirUITests.swift */; };
84EDAB1626839CFE003A0AE2 /* ResearchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8492BEBD267921B700088582 /* ResearchKit.framework */; };
84EDAB1726839CFE003A0AE2 /* ResearchKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8492BEBD267921B700088582 /* ResearchKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
84EDAB2026839D03003A0AE2 /* SMART in Frameworks */ = {isa = PBXBuildFile; productRef = 84EDAB1F26839D03003A0AE2 /* SMART */; };
@ -112,22 +110,20 @@
84C0C50C26AF4FBD00FF5E35 /* SecretStoreError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretStoreError.swift; sourceTree = "<group>"; };
84C0C51426AF706300FF5E35 /* ViewControllerBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerBase.swift; sourceTree = "<group>"; };
84C2A56226A9E6A9003F59C0 /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = "<group>"; };
84CBB8A4269E005300F2D507 /* FHIRtoRK.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FHIRtoRK.swift; sourceTree = "<group>"; };
84CBB8AF269E007100F2D507 /* RKtoFHIR.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RKtoFHIR.swift; sourceTree = "<group>"; };
84D04DC726A99D7C001BA808 /* CustomTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTableViewCell.swift; sourceTree = "<group>"; };
84CBB8A4269E005300F2D507 /* FhirToResearchKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FhirToResearchKit.swift; sourceTree = "<group>"; };
84CBB8AF269E007100F2D507 /* ResearchKitToFhir.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResearchKitToFhir.swift; sourceTree = "<group>"; };
84D04DC726A99D7C001BA808 /* QuestionnaireListTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestionnaireListTableViewCell.swift; sourceTree = "<group>"; };
84DBBCF326BB3E400007EB33 /* FhirTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FhirTypes.swift; sourceTree = "<group>"; };
84EDAAB02683969D003A0AE2 /* researchKitOnFhir.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = researchKitOnFhir.app; sourceTree = BUILT_PRODUCTS_DIR; };
84EDAAB22683969D003A0AE2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
84EDAAB42683969D003A0AE2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
84EDAAB62683969D003A0AE2 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
84EDAAB92683969D003A0AE2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
84EDAABB268396A1003A0AE2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
84EDAABE268396A1003A0AE2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
84EDAAC0268396A1003A0AE2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
84EDAAC5268396A2003A0AE2 /* researchKitOnFhirTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = researchKitOnFhirTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
84EDAAC9268396A2003A0AE2 /* researchKitOnFhirTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = researchKitOnFhirTests.swift; sourceTree = "<group>"; };
84EDAACB268396A2003A0AE2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
84EDAAD0268396A2003A0AE2 /* researchKitOnFhirUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = researchKitOnFhirUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
84EDAAD4268396A2003A0AE2 /* researchKitOnFhirUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = researchKitOnFhirUITests.swift; sourceTree = "<group>"; };
84EDAAD6268396A2003A0AE2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -194,8 +190,9 @@
isa = PBXGroup;
children = (
844D31C226A514AD00010466 /* QuestionnaireType.swift */,
84D04DC726A99D7C001BA808 /* CustomTableViewCell.swift */,
84D04DC726A99D7C001BA808 /* QuestionnaireListTableViewCell.swift */,
84814BB226AA05AE007DF055 /* QListCategory.swift */,
84DBBCF326BB3E400007EB33 /* FhirTypes.swift */,
);
path = Model;
sourceTree = "<group>";
@ -205,7 +202,6 @@
children = (
845A1515269F68640011B506 /* LandingScreenViewController.swift */,
845A152F269F6DA30011B506 /* SurveyListViewController.swift */,
84EDAAB62683969D003A0AE2 /* ViewController.swift */,
84C0C51426AF706300FF5E35 /* ViewControllerBase.swift */,
);
path = ViewControllers;
@ -276,7 +272,6 @@
84EDAAC8268396A2003A0AE2 /* researchKitOnFhirTests */ = {
isa = PBXGroup;
children = (
84EDAAC9268396A2003A0AE2 /* researchKitOnFhirTests.swift */,
84EDAACB268396A2003A0AE2 /* Info.plist */,
);
path = researchKitOnFhirTests;
@ -285,7 +280,6 @@
84EDAAD3268396A2003A0AE2 /* researchKitOnFhirUITests */ = {
isa = PBXGroup;
children = (
84EDAAD4268396A2003A0AE2 /* researchKitOnFhirUITests.swift */,
84EDAAD6268396A2003A0AE2 /* Info.plist */,
);
path = researchKitOnFhirUITests;
@ -295,8 +289,8 @@
isa = PBXGroup;
children = (
8462E91E26B4C409003CC235 /* ResponseBuilders */,
84CBB8A4269E005300F2D507 /* FHIRtoRK.swift */,
84CBB8AF269E007100F2D507 /* RKtoFHIR.swift */,
84CBB8A4269E005300F2D507 /* FhirToResearchKit.swift */,
84CBB8AF269E007100F2D507 /* ResearchKitToFhir.swift */,
);
path = Conversion;
sourceTree = "<group>";
@ -465,7 +459,6 @@
buildActionMask = 2147483647;
files = (
840584D42684F0C200986AC5 /* ServerExtensions.swift in Sources */,
84EDAAB72683969D003A0AE2 /* ViewController.swift in Sources */,
840584DC2685055100986AC5 /* ExternalStoreDelegate.swift in Sources */,
8462E90726B4C054003CC235 /* DateTimeResponseBuilder.swift in Sources */,
84814BB326AA05AE007DF055 /* QListCategory.swift in Sources */,
@ -476,14 +469,15 @@
8462E91726B4C36F003CC235 /* ChoiceResponseBuilder.swift in Sources */,
8462E8F726B4BE11003CC235 /* DecimalResponseBuilder.swift in Sources */,
84EDAAB32683969D003A0AE2 /* AppDelegate.swift in Sources */,
84D04DC826A99D7C001BA808 /* CustomTableViewCell.swift in Sources */,
84D04DC826A99D7C001BA808 /* QuestionnaireListTableViewCell.swift in Sources */,
8462E8D326B4B46D003CC235 /* FHIRResponseBuilder.swift in Sources */,
8496FCB626935B41008E54C1 /* ConfigHelper.swift in Sources */,
8462E8DB26B4B616003CC235 /* TextStringResponseBuilder.swift in Sources */,
84DBBCF426BB3E400007EB33 /* FhirTypes.swift in Sources */,
844D31C326A514AD00010466 /* QuestionnaireType.swift in Sources */,
84C0C50D26AF4FBD00FF5E35 /* SecretStoreError.swift in Sources */,
84CBB8B0269E007100F2D507 /* RKtoFHIR.swift in Sources */,
84CBB8A5269E005300F2D507 /* FHIRtoRK.swift in Sources */,
84CBB8B0269E007100F2D507 /* ResearchKitToFhir.swift in Sources */,
84CBB8A5269E005300F2D507 /* FhirToResearchKit.swift in Sources */,
84C2A56326A9E6A9003F59C0 /* UIView.swift in Sources */,
8462E8E326B4BCA8003CC235 /* IntegerResponseBuilder.swift in Sources */,
84EDAAB52683969D003A0AE2 /* SceneDelegate.swift in Sources */,
@ -496,7 +490,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
84EDAACA268396A2003A0AE2 /* researchKitOnFhirTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -504,7 +497,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
84EDAAD5268396A2003A0AE2 /* researchKitOnFhirUITests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

Просмотреть файл

@ -1,6 +1,9 @@
//
// AppDelegate.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import UIKit

Просмотреть файл

@ -78,8 +78,8 @@
<color key="titleColor" systemColor="labelColor"/>
</state>
</button>
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EIt-oJ-O5e">
<rect key="frame" x="195" y="801" width="166" height="32"/>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EIt-oJ-O5e">
<rect key="frame" x="256" y="801" width="105" height="32"/>
<constraints>
<constraint firstAttribute="height" constant="32" id="jPB-sy-bfc"/>
</constraints>
@ -120,15 +120,16 @@
<constraints>
<constraint firstItem="4ei-Wf-kgh" firstAttribute="top" secondItem="vuY-en-wRh" secondAttribute="bottom" constant="31" id="3UX-3q-p3H"/>
<constraint firstItem="49m-7K-ptL" firstAttribute="centerX" secondItem="vuY-en-wRh" secondAttribute="centerX" id="7lo-zl-Yhn"/>
<constraint firstItem="AOk-Yi-4iH" firstAttribute="bottom" secondItem="EIt-oJ-O5e" secondAttribute="bottom" constant="29" id="C9H-Vj-lJg"/>
<constraint firstItem="49m-7K-ptL" firstAttribute="top" secondItem="Pgc-nE-M0e" secondAttribute="top" constant="247" id="DsP-Yu-zpg"/>
<constraint firstItem="49m-7K-ptL" firstAttribute="centerX" secondItem="AOk-Yi-4iH" secondAttribute="centerX" id="Nw9-pK-uU7"/>
<constraint firstItem="AOk-Yi-4iH" firstAttribute="trailing" secondItem="EIt-oJ-O5e" secondAttribute="trailing" constant="53" id="QRW-TC-gzg"/>
<constraint firstItem="EIt-oJ-O5e" firstAttribute="leading" secondItem="AOk-Yi-4iH" secondAttribute="leading" constant="231" id="TZj-9k-ZyN"/>
<constraint firstItem="49m-7K-ptL" firstAttribute="trailing" secondItem="4ei-Wf-kgh" secondAttribute="trailing" id="XMW-S0-XP4"/>
<constraint firstAttribute="bottom" secondItem="4ei-Wf-kgh" secondAttribute="bottom" constant="196" id="YxI-43-CPB"/>
<constraint firstItem="49m-7K-ptL" firstAttribute="centerX" secondItem="AOk-Yi-4iH" secondAttribute="centerX" id="e3K-lZ-I9z"/>
<constraint firstItem="49m-7K-ptL" firstAttribute="centerX" secondItem="4ei-Wf-kgh" secondAttribute="centerX" id="eoh-6Q-tvt"/>
<constraint firstItem="AOk-Yi-4iH" firstAttribute="bottom" secondItem="EIt-oJ-O5e" secondAttribute="bottom" constant="29" id="kDB-11-GbK"/>
<constraint firstItem="AOk-Yi-4iH" firstAttribute="trailing" secondItem="EIt-oJ-O5e" secondAttribute="trailing" constant="53" id="naZ-RK-Fo0"/>
<constraint firstItem="49m-7K-ptL" firstAttribute="trailing" secondItem="vuY-en-wRh" secondAttribute="trailing" id="s3B-dT-roj"/>
<constraint firstItem="49m-7K-ptL" firstAttribute="centerX" secondItem="f14-ja-cxb" secondAttribute="centerX" id="s5x-ro-8BF"/>
<constraint firstItem="49m-7K-ptL" firstAttribute="width" secondItem="Pgc-nE-M0e" secondAttribute="width" multiplier="0.434783" id="uv0-3Q-yo9"/>

Просмотреть файл

@ -1,6 +1,9 @@
//
// ConfigHelper.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,57 +1,56 @@
//
// FHIRtoRK.swift
// researchKitOnFhir
// FhirToResearchKit.swift
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
import SMART
import ResearchKit
public class FHIRtoRKConverter {
public class FhirToResearchKitConverter {
static var FHIRQuestionnaire: Questionnaire = Questionnaire()
static var FHIRQuestionMap: [String: QuestionnaireItem] = [:]
static var fhirQuestionnaire: Questionnaire = Questionnaire()
static var fhirQuestionMap: [String: QuestionnaireItem] = [:]
static var currentIndex = Int()
static var ORKStepQuestionnaire: [ORKStep] = [ORKStep]()
init() {
// do nothing
}
func FHIRQuestionListToRKQuestions (questions: [QuestionnaireItem], questionnaireTitle: String) -> [ORKStep] {
func fhirQuestionListToResearchKitQuestions (questions: [QuestionnaireItem], questionnaireTitle: String) -> [ORKStep] {
var surveySteps = [ORKStep]()
for question in questions {
// ensures the question text is not empty
if question.text != nil || question.type?.rawValue == "group" {
if question.text != nil || question.type?.rawValue == fhirTypes.group {
switch(question.type?.rawValue){
case "group":
let newFormStep = createGroupItem(question: question, title: questionnaireTitle)
if newFormStep.formItems != nil {
if newFormStep.formItems!.count > 0 {
surveySteps += [newFormStep]
case fhirTypes.group:
if let newFormStep = createGroupItem(question: question, title: questionnaireTitle){
if let formItems = newFormStep.formItems {
if formItems.count > 0 {
surveySteps += [newFormStep]
}
}
}
case "text",
"string",
"integer",
"boolean",
"decimal",
"time",
"dateTime",
"choice",
"date":
case fhirTypes.text,
fhirTypes.string,
fhirTypes.integer,
fhirTypes.boolean,
fhirTypes.decimal,
fhirTypes.time,
fhirTypes.dateTime,
fhirTypes.choice,
fhirTypes.date:
surveySteps += [buildNewQuestion(question: question, questionnaireTitle: questionnaireTitle)]
case .none:
question.type = QuestionnaireItemType(rawValue: "text")
question.type = QuestionnaireItemType(rawValue: fhirTypes.text)
surveySteps += [buildNewQuestion(question: question, questionnaireTitle: questionnaireTitle)]
print("none")
case .some(_):
question.type = QuestionnaireItemType(rawValue: "text")
question.type = QuestionnaireItemType(rawValue: fhirTypes.text)
surveySteps += [buildNewQuestion(question: question, questionnaireTitle: questionnaireTitle)]
print("CONVERSION some")
}
@ -61,8 +60,16 @@ public class FHIRtoRKConverter {
}
// converts FHIR "group" type to ORKFormStep with list of ORKFormItems
func createGroupItem (question: QuestionnaireItem, title: String) -> ORKFormStep {
let stepForm = ORKFormStep(identifier: question.linkId!.string)
func createGroupItem (question: QuestionnaireItem, title: String) -> ORKFormStep? {
var stepForm: ORKFormStep
if let linkId = question.linkId {
stepForm = ORKFormStep(identifier: linkId.string)
} else {
return nil
}
stepForm.title = title
var stepFormItems = [ORKFormItem]()
@ -101,35 +108,35 @@ public class FHIRtoRKConverter {
if question.type?.rawValue != nil {
switch(question.type?.rawValue){
case "text":
case fhirTypes.text:
if question.maxLength == nil {
answer = ORKTextAnswerFormat()
} else {
answer = ORKTextAnswerFormat(maximumLength: question.maxLength!.int)
}
case "string":
case fhirTypes.string:
answer = ORKTextAnswerFormat()
case "integer":
case fhirTypes.integer:
answer = ORKNumericAnswerFormat.integerAnswerFormat(withUnit: "")
case "boolean":
case fhirTypes.boolean:
answer = ORKBooleanAnswerFormat.booleanAnswerFormat()
case "decimal":
case fhirTypes.decimal:
answer = ORKNumericAnswerFormat.decimalAnswerFormat(withUnit: "")
case "time":
case fhirTypes.time:
answer = ORKTimeOfDayAnswerFormat()
case "dateTime":
case fhirTypes.dateTime:
answer = ORKDateAnswerFormat(style: ORKDateAnswerStyle.dateAndTime)
case "date":
case fhirTypes.date:
answer = ORKDateAnswerFormat(style: ORKDateAnswerStyle.date)
case "choice":
case fhirTypes.choice:
let answerOptions = getTextChoiceFromFHIRType(question: question)
if answerOptions.count > 0 {
@ -210,7 +217,7 @@ public class FHIRtoRKConverter {
self.buildQuestionMap(questionItems: questionnaire.item!)
steps = self.FHIRQuestionListToRKQuestions(questions: questionnaire.item!, questionnaireTitle: questionnaire.title?.string ?? "")
steps = self.fhirQuestionListToResearchKitQuestions(questions: questionnaire.item!, questionnaireTitle: questionnaire.title?.string ?? "")
}
@ -221,10 +228,10 @@ public class FHIRtoRKConverter {
func buildQuestionMap (questionItems: [QuestionnaireItem]) {
for questionItem in questionItems {
if questionItem.type?.rawValue == "group" {
if questionItem.type?.rawValue == fhirTypes.group {
buildQuestionMap(questionItems: questionItem.item!)
} else {
FHIRtoRKConverter.FHIRQuestionMap[questionItem.linkId!.string] = questionItem
FhirToResearchKitConverter.fhirQuestionMap[questionItem.linkId!.string] = questionItem
}
}
}

Просмотреть файл

@ -1,81 +0,0 @@
//
// RKtoFHIR.swift
// researchKitOnFhir
//
import Foundation
import SMART
import ResearchKit
public class RKtoFHIRConverter {
init() {
// do nothing
}
func RKQuestionResponseToFHIR (results: ORKTaskViewController) -> QuestionnaireResponse {
let taskResult = results.result.results
let questionnaireResponse = QuestionnaireResponse()
var FHIRQuestionResponses = [QuestionnaireResponseItem]()
if taskResult != nil {
for stepResults in taskResult! as! [ORKStepResult]
{
if stepResults.results != nil {
for result in stepResults.results!
{
var newQuestionResponse: QuestionnaireResponseItem
let type = FHIRtoRKConverter.FHIRQuestionMap[result.identifier]?.type?.rawValue
switch(type) {
case "text", "string":
newQuestionResponse = convertTextResponse(result: result)
case "integer":
let integerConverter = IntegerResponseBuilder(result: result)
newQuestionResponse = integerConverter.convertResponse()
case "decimal":
let decimalConverter = DecimalResponseBuilder(result: result)
newQuestionResponse = decimalConverter.convertResponse()
case "boolean":
let booleanConverter = BooleanResponseBuilder(result: result)
newQuestionResponse = booleanConverter.convertResponse()
case "time","dateTime", "date":
let dateTimeConverter = DateTimeResponseBuilder(result: result)
newQuestionResponse = dateTimeConverter.convertResponse(type: type!)
case "choice":
let choiceConverter = ChoiceResponseBuilder(result: result)
newQuestionResponse = choiceConverter.convertResponse()
default:
newQuestionResponse = convertTextResponse(result: result)
}
if newQuestionResponse.answer != nil {
FHIRQuestionResponses += [newQuestionResponse]
}
}
}
}
}
questionnaireResponse.item = FHIRQuestionResponses
questionnaireResponse.status = QuestionnaireResponseStatus.completed
return questionnaireResponse
}
func convertTextResponse(result: ORKResult) -> QuestionnaireResponseItem {
let textConverter = TextStringResponseBuilder(result: result)
return textConverter.convertResponse()
}
}

Просмотреть файл

@ -0,0 +1,82 @@
//
// ResearchKitToFhir.swift
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
import SMART
import ResearchKit
struct ResponseMessage {
static let noResponse = "no response given"
}
public class ResearchKitToFhirConverter {
func researchKitQuestionResponseToFhir (results: ORKTaskViewController) -> QuestionnaireResponse {
let questionnaireResponse = QuestionnaireResponse()
var FHIRQuestionResponses = [QuestionnaireResponseItem]()
if let taskResult = results.result.results as? [ORKStepResult] {
for stepResults in taskResult
{
if let stepResultResults = stepResults.results {
for result in stepResultResults
{
var newQuestionResponse: QuestionnaireResponseItem
if let type = FhirToResearchKitConverter.fhirQuestionMap[result.identifier]?.type?.rawValue {
switch(type) {
case fhirTypes.text, fhirTypes.string:
newQuestionResponse = convertTextResponse(result: result)
case fhirTypes.integer:
let integerConverter = IntegerResponseBuilder(result: result)
newQuestionResponse = integerConverter.convertResponse()
case fhirTypes.decimal:
let decimalConverter = DecimalResponseBuilder(result: result)
newQuestionResponse = decimalConverter.convertResponse()
case fhirTypes.boolean:
let booleanConverter = BooleanResponseBuilder(result: result)
newQuestionResponse = booleanConverter.convertResponse()
case fhirTypes.time,fhirTypes.dateTime, fhirTypes.date:
let dateTimeConverter = DateTimeResponseBuilder(result: result)
newQuestionResponse = dateTimeConverter.convertResponse(type: type)
case fhirTypes.choice:
let choiceConverter = ChoiceResponseBuilder(result: result)
newQuestionResponse = choiceConverter.convertResponse()
default:
newQuestionResponse = convertTextResponse(result: result)
}
if newQuestionResponse.answer != nil {
FHIRQuestionResponses += [newQuestionResponse]
}
}
}
}
}
}
questionnaireResponse.item = FHIRQuestionResponses
questionnaireResponse.status = QuestionnaireResponseStatus.completed
return questionnaireResponse
}
func convertTextResponse(result: ORKResult) -> QuestionnaireResponseItem {
let textConverter = TextStringResponseBuilder(result: result)
return textConverter.convertResponse()
}
}

Просмотреть файл

@ -1,6 +1,9 @@
//
// BooleanResponseBuilder.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
@ -11,11 +14,11 @@ public class BooleanResponseBuilder: FHIRResponseBuilder {
public func convertResponse() -> QuestionnaireResponseItem {
let newResult = result as! ORKBooleanQuestionResult
let newResult = result as? ORKBooleanQuestionResult
let newQuestionResponseAnswer = QuestionnaireResponseItemAnswer()
if newResult.booleanAnswer != nil {
let newAnswerAsFHIRBoolean = FHIRBool(booleanLiteral: (newResult.booleanAnswer != nil))
if let booleanAnswer = newResult?.booleanAnswer {
let newAnswerAsFHIRBoolean = FHIRBool(booleanLiteral: booleanAnswer.boolValue)
newQuestionResponseAnswer.valueBoolean = newAnswerAsFHIRBoolean
newQuestionResponse.answer = [QuestionnaireResponseItemAnswer]()

Просмотреть файл

@ -1,6 +1,9 @@
//
// ChoiceResponseBuilder.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
@ -11,25 +14,27 @@ public class ChoiceResponseBuilder: FHIRResponseBuilder {
public func convertResponse() -> QuestionnaireResponseItem {
let newResult = result as! ORKChoiceQuestionResult
let newQuestionResponseAnswer = QuestionnaireResponseItemAnswer()
if newResult.answer != nil {
let answerArray = newResult.answer as! NSArray
if let newResult = result as? ORKChoiceQuestionResult {
var newAnswerAsFHIRString = FHIRString("no response")
var newAnswerAsFHIRString: FHIRString
if answerArray.count > 0 {
// FHIR standard only allows for one answer to be selected from multiple choice question
newAnswerAsFHIRString.string = answerArray[0] as! String
}
newQuestionResponseAnswer.valueString = newAnswerAsFHIRString
newQuestionResponse.answer = [QuestionnaireResponseItemAnswer]()
if newQuestionResponseAnswer.valueString != nil && newQuestionResponse.answer != nil {
newQuestionResponse.answer! += [newQuestionResponseAnswer]
if newResult.answer != nil {
if let answerArray = newResult.answer as? NSArray {
if answerArray.count > 0 {
// FHIR standard only allows for one answer to be selected from multiple choice question
newAnswerAsFHIRString = FHIRString(answerArray[0] as? String ?? ResponseMessage.noResponse)
newQuestionResponseAnswer.valueString = newAnswerAsFHIRString
newQuestionResponse.answer = [QuestionnaireResponseItemAnswer]()
if newQuestionResponse.answer != nil {
newQuestionResponse.answer! += [newQuestionResponseAnswer]
}
}
}
}
}

Просмотреть файл

@ -1,6 +1,9 @@
//
// DateTimeResponseBuilder.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
@ -11,13 +14,13 @@ public class DateTimeResponseBuilder: FHIRResponseBuilder {
public func convertResponse(type: String) -> QuestionnaireResponseItem {
let newQuestionResponseAnswer = QuestionnaireResponseItemAnswer()
switch(type) {
case "dateTime":
let newResult = result as! ORKDateQuestionResult
let newQuestionResponseAnswer = QuestionnaireResponseItemAnswer()
if newResult.dateAnswer != nil {
if let newResult = result as? ORKDateQuestionResult {
let newAnswerAsFHIRDateTime = getFHIRDateTime(result: newResult, includeTime: true)
newQuestionResponseAnswer.valueDateTime = newAnswerAsFHIRDateTime
@ -29,10 +32,8 @@ public class DateTimeResponseBuilder: FHIRResponseBuilder {
return newQuestionResponse
case "time":
let newResult = result as! ORKTimeOfDayQuestionResult
let newQuestionResponseAnswer = QuestionnaireResponseItemAnswer()
if newResult.dateComponentsAnswer != nil {
if let newResult = result as? ORKTimeOfDayQuestionResult {
let newAnswerAsFHIRTime = getFHIRTime(result: newResult)
newQuestionResponseAnswer.valueTime = newAnswerAsFHIRTime
@ -43,10 +44,8 @@ public class DateTimeResponseBuilder: FHIRResponseBuilder {
}
case "date":
let newResult = result as! ORKDateQuestionResult
let newQuestionResponseAnswer = QuestionnaireResponseItemAnswer()
if newResult.dateAnswer != nil {
if let newResult = result as? ORKDateQuestionResult {
let newAnswerAsFHIRDateTime = getFHIRDate(result: newResult)
newQuestionResponseAnswer.valueDate = newAnswerAsFHIRDateTime
@ -62,25 +61,29 @@ public class DateTimeResponseBuilder: FHIRResponseBuilder {
return newQuestionResponse
}
func getFHIRDateTime(result: ORKDateQuestionResult, includeTime: Bool) -> DateTime {
func getFHIRDateTime(result: ORKDateQuestionResult, includeTime: Bool) -> DateTime? {
let resultDate = getFHIRDate(result: result)
// set default time in case no time selected
var resultTime = FHIRTime(hour: 0, minute: 0, second: 0)
var resultTimeZone = TimeZone.current
if includeTime {
resultTime = getTimeFromDateTime(result: result)
// date is required for FHIR DateTime; time is optional
if let resultDate = getFHIRDate(result: result) {
if result.timeZone != nil {
resultTimeZone = result.timeZone!
// set default time in case no time selected
var resultTime = FHIRTime(hour: 0, minute: 0, second: 0)
var resultTimeZone = TimeZone.current
if includeTime {
resultTime = getTimeFromDateTime(result: result)
if result.timeZone != nil {
resultTimeZone = result.timeZone!
}
}
let resultDateTime = DateTime(date: resultDate, time: resultTime, timeZone: resultTimeZone)
return resultDateTime
}
let resultDateTime = DateTime(date: resultDate, time: resultTime, timeZone: resultTimeZone)
return resultDateTime
return nil
}
func getTimeFromDateTime(result: ORKDateQuestionResult) -> FHIRTime {
@ -96,18 +99,26 @@ public class DateTimeResponseBuilder: FHIRResponseBuilder {
}
func getFHIRDate(result: ORKDateQuestionResult) -> FHIRDate {
func getFHIRDate(result: ORKDateQuestionResult) -> FHIRDate? {
let calendar = Calendar.current
var components = calendar.dateComponents([.year], from: result.dateAnswer!)
let resultYear = components.year!
components = calendar.dateComponents([.month], from: result.dateAnswer!)
let resultMonth = UInt8(exactly: components.month!)
components = calendar.dateComponents([.day], from: result.dateAnswer!)
let resultDay = UInt8(exactly: components.day!)
let resultDate = FHIRDate(year: resultYear, month: resultMonth, day: resultDay)
if let dateResult = result.dateAnswer {
var components = calendar.dateComponents([.year], from: dateResult)
// year is a required field for FHIRDate; month and day are optional
if let resultYear = components.year {
components = calendar.dateComponents([.month], from: dateResult)
let resultMonth = UInt8(exactly: components.month ?? 0)
components = calendar.dateComponents([.day], from: dateResult)
let resultDay = UInt8(exactly: components.day ?? 0)
let resultDate = FHIRDate(year: resultYear, month: resultMonth, day: resultDay)
return resultDate
}
}
return resultDate
return nil
}
func getFHIRTime(result: ORKTimeOfDayQuestionResult) -> FHIRTime {

Просмотреть файл

@ -1,6 +1,9 @@
//
// DecimalResponseBuilder.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
@ -11,11 +14,11 @@ public class DecimalResponseBuilder: FHIRResponseBuilder {
public func convertResponse() -> QuestionnaireResponseItem {
let newResult = result as! ORKNumericQuestionResult
let newResult = result as? ORKNumericQuestionResult
let newQuestionResponseAnswer = QuestionnaireResponseItemAnswer()
if newResult.numericAnswer != nil {
let newAnswerAsFHIRDecimal = FHIRDecimal(newResult.numericAnswer as! Decimal)
if let numericAnswer = newResult?.numericAnswer as? Decimal {
let newAnswerAsFHIRDecimal = FHIRDecimal(numericAnswer)
newQuestionResponseAnswer.valueDecimal = newAnswerAsFHIRDecimal
newQuestionResponse.answer = [QuestionnaireResponseItemAnswer]()

Просмотреть файл

@ -1,6 +1,9 @@
//
// FHIRResponseBuilder.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,6 +1,9 @@
//
// IntegerResponseBuilder.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
@ -11,11 +14,11 @@ public class IntegerResponseBuilder: FHIRResponseBuilder {
public func convertResponse() -> QuestionnaireResponseItem {
let newResult = result as! ORKNumericQuestionResult
let newResult = result as? ORKNumericQuestionResult
let newQuestionResponseAnswer = QuestionnaireResponseItemAnswer()
if newResult.numericAnswer != nil {
let newAnswerAsFHIRInteger = FHIRInteger(newResult.numericAnswer as! Int32)
if let numericAnswer = newResult?.numericAnswer as? Int32 {
let newAnswerAsFHIRInteger = FHIRInteger(numericAnswer)
newQuestionResponseAnswer.valueInteger = newAnswerAsFHIRInteger
newQuestionResponse.answer = [QuestionnaireResponseItemAnswer]()

Просмотреть файл

@ -1,6 +1,9 @@
//
// TextStringResponseBuilder.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
@ -11,17 +14,24 @@ public class TextStringResponseBuilder: FHIRResponseBuilder {
public func convertResponse() -> QuestionnaireResponseItem {
let newResult = self.result as! ORKTextQuestionResult
let newQuestionResponseAnswer = QuestionnaireResponseItemAnswer()
if newResult.textAnswer != nil {
let newAnswerAsFHIRString = FHIRString(newResult.textAnswer!)
newQuestionResponseAnswer.valueString = newAnswerAsFHIRString
newQuestionResponse.answer = [QuestionnaireResponseItemAnswer]()
if newQuestionResponseAnswer.valueString != nil && newQuestionResponse.answer != nil {
newQuestionResponse.answer! += [newQuestionResponseAnswer]
// set default to no response in case result is nil
newQuestionResponseAnswer.valueString = FHIRString(ResponseMessage.noResponse)
if let newResult = self.result as? ORKTextQuestionResult {
if let textAnswer = newResult.textAnswer {
let newAnswerAsFHIRString = FHIRString(textAnswer)
newQuestionResponseAnswer.valueString = newAnswerAsFHIRString
}
}
newQuestionResponse.answer = [QuestionnaireResponseItemAnswer]()
if newQuestionResponseAnswer.valueString != nil && newQuestionResponse.answer != nil {
newQuestionResponse.answer! += [newQuestionResponseAnswer]
}
return newQuestionResponse
}

Просмотреть файл

@ -1,6 +1,9 @@
//
// ExternalStoreDelegateError.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,8 +1,9 @@
//
// SecretStoreError.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Created by admin on 7/26/21.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,6 +1,9 @@
//
// ServerExtensions.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,6 +1,9 @@
//
// UIView.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,6 +1,9 @@
//
// ExternalStoreDelegate.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -0,0 +1,22 @@
//
// FhirTypes.swift
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
struct fhirTypes {
static let group = "group"
static let text = "text"
static let string = "string"
static let integer = "integer"
static let boolean = "boolean"
static let decimal = "decimal"
static let time = "time"
static let dateTime = "dateTime"
static let date = "date"
static let choice = "choice"
}

Просмотреть файл

@ -1,6 +1,9 @@
//
// QListCategory.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,14 +1,18 @@
//
// CustomTableViewCell.swift
// researchKitOnFhir
// QuestionnaireListTableViewCell.swift
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation
import UIKit
public class CustomTableViewCell: UITableViewCell {
public class QuestionnaireListTableViewCell: UITableViewCell {
var questionnaireLabel = UILabel()
static let buttonCellIdentifier = "buttonCell"
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)

Просмотреть файл

@ -1,6 +1,9 @@
//
// QuestionnaireType.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,8 +1,8 @@
# ResearchKit-on-Fhir
ResearchKitOnFhir is an iOS template app that integrates Apple ResearchKit with FHIR® by:
1. Automating the import of [FHIR® Questionnaires](https://www.hl7.org/fhir/questionnaire.html#resource) from a FHIR® Server and their conversion to corresponding ResearchKit UI modules
2. Automating the conversion of ResearchKit Survey responses to [FHIR® QuestionnaireResponses](https://www.hl7.org/fhir/questionnaireresponse.html#resource) and their export to a FHIR® Server
ResearchKitOnFhir is an iOS template app that integrates Apple ResearchKit with FHIR by:
1. Automating the import of [FHIR Questionnaires](https://www.hl7.org/fhir/questionnaire.html#resource) from a FHIR Server and their conversion to corresponding ResearchKit UI modules
2. Automating the conversion of ResearchKit Survey responses to [FHIR QuestionnaireResponses](https://www.hl7.org/fhir/questionnaireresponse.html#resource) and their export to a FHIR Server
## Supported Types
@ -20,13 +20,13 @@ ResearchKitOnFhir currently supports conversion between the following [ResearchK
| date | ORKDateAnswerFormat | style: ORKDateAnswerStyle.date |
| dateTime | ORKDateAnswerFormat | style: ORKDateAnswerStyle.dateAndTime |
**Threshold of 10 arbitrarily set in func MultipleChoiceFormat in FHIRtoRK.swift: if all responses are shorter than 10 characters, Value Picker format is displayed. Otherwise, TextChoice format is displayed.
**Threshold of 10 arbitrarily set in func MultipleChoiceFormat in FhirToResearchKit.swift: if all responses are shorter than 10 characters, Value Picker format is displayed. Otherwise, TextChoice format is displayed.
## Authentication and Configuration
ResearchKitOnFhir uses [SMART on FHIR](https://docs.smarthealthit.org) to integrate the app with a FHIR® Server. Current implementation supports configuration through the Config.json file, which the user populates with their FHIR® Server URL, SMART Client ID, and Patient ID, corresponding to ID of [Patient Resource](https://www.hl7.org/fhir/patient.html#resource) linked to intended app user. For example, a Patient who is accessed in the FHIR® Server through the URI "Patient/samplePatientName" will require a Config.json file with:
ResearchKitOnFhir uses [SMART on FHIR](https://docs.smarthealthit.org) to integrate the app with a FHIR Server. Current implementation supports configuration through the Config.json file, which the user populates with their FHIR Server URL, SMART Client ID, and Patient ID (the FHIR id of the [Patient Resource](https://www.hl7.org/fhir/patient.html#resource) representing the intended app user). For example, a Patient who is accessed in the FHIR Server through the URI "Patient/samplePatientName" will require a Config.json file with:
```
```json
"patientId": "samplePatientName"
```
Implementation is still needed to handle authentication token timeout (see TODO in AppDelegate.swift).
@ -34,14 +34,14 @@ Implementation is still needed to handle authentication token timeout (see TODO
## Building Questionnaires
Each [FHIR® Questionnaire](https://www.hl7.org/fhir/questionnaire.html#resource) must be associated with a [FHIR® Task](https://www.hl7.org/fhir/task.html#resource), which is linked to the [FHIR® Patient](https://www.hl7.org/fhir/patient.html#resource) assigned to it through the "owner" field, and linked to the Questionnaire it assigns through the "basedOn" field. The Patient will only be asked to complete those questionnaires that are linked to a Task without status set to "completed".
Each [FHIR Questionnaire](https://www.hl7.org/fhir/questionnaire.html#resource) must be associated with a [FHIR® Task](https://www.hl7.org/fhir/task.html#resource), which is linked to the [FHIR Patient](https://www.hl7.org/fhir/patient.html#resource) assigned to it through the "owner" field, and linked to the Questionnaire it assigns through the "basedOn" field. The Patient will only be asked to complete those questionnaires that are linked to a Task without status set to "completed".
When the user completes a Survey through the app, a [FHIR® QuestionnaireResponse](https://www.hl7.org/fhir/questionnaireresponse.html#resource) will be created and linked to the corresponding Questionnaire through the "questionnaire" field. Each questionnaire response (if not nil) of the QuestionnaireResponse will be linked to its corresponding question in the corresponding Questionnaire through the "linkId" field in both resources.
When the user completes a Survey through the app, a [FHIR QuestionnaireResponse](https://www.hl7.org/fhir/questionnaireresponse.html#resource) will be created and linked to the corresponding Questionnaire through the "questionnaire" field. Each questionnaire response (if not nil) of the QuestionnaireResponse will be linked to its corresponding question in the corresponding Questionnaire through the "linkId" field in both resources.
Below is a set of sample FHIR® Resources that have all fields required to facilitate the functionality of the app:
Below is a set of sample FHIR Resources that have all fields required to facilitate the functionality of the app:
### Sample Task:
```
```json
{
"resourceType":"Task",
"id":"sampleTask1",
@ -63,7 +63,7 @@ Below is a set of sample FHIR® Resources that have all fields required to facil
```
### Corresponding Questionnaire:
```
```json
{
"resourceType":"Questionnaire",
"id":"bloodSugar",
@ -145,7 +145,7 @@ Below is a set of sample FHIR® Resources that have all fields required to facil
### Sample QuestionnaireResponse
Generated by the app upon completion of above Questionnaire
```
```json
{
"resourceType":"QuestionnaireResponse",
"id":"7a382ed7-5390-4b45-9ab6-d33b85f1f625",
@ -210,4 +210,4 @@ Generated by the app upon completion of above Questionnaire
## Adding Additional Types
The addition of FHIR® QuestionTypes and their conversion to and from ResearchKit UI formats requires additions to func RKQuestionResponseToFHIR in RKtoFHIR.swift and func FHIRQuestionListToRKQuestions in FHIRtoRK.swift.
The addition of FHIR QuestionTypes and their conversion to and from ResearchKit UI formats requires additions to func researchKitQuestionResponseToFhir in ResearchKitToFhir.swift and func fhirQuestionListToResearchKitQuestions in FhirToResearchKit.swift.

Просмотреть файл

@ -1,6 +1,9 @@
//
// SceneDelegate.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import UIKit

Просмотреть файл

@ -1,6 +1,9 @@
//
// SecretStore.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,6 +1,9 @@
//
// LandingPageViewController.swift
// researchKitOnFhir
// LandingScreenViewController.swift
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import UIKit
@ -18,7 +21,9 @@ class LandingScreenViewController: ViewControllerBase {
super.viewDidLoad()
#if targetEnvironment(simulator)
configMessageLabel.text = "Drag the Config.json file onto the Simulator screen to begin."
configMessageLabel.text = "Drag the Config.json file onto the Simulator screen to begin."
#else
configMessageLabel.text = "Tap on your configuration file and choose this application to open it."
#endif
self.authenticatedPatientButton.isHidden = true

Просмотреть файл

@ -1,6 +1,9 @@
//
// SurveyListViewController.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import UIKit
@ -17,10 +20,6 @@ class SurveyListViewController: UIViewController {
let tableView = UITableView()
static var QList = [QListCategory]()
struct Cells {
static let buttonCell = "buttonCell"
}
struct SectionTitles {
static let toDo = "Requested"
static let complete = "Complete"
@ -28,7 +27,7 @@ class SurveyListViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: Cells.buttonCell)
tableView.register(QuestionnaireListTableViewCell.self, forCellReuseIdentifier: QuestionnaireListTableViewCell.buttonCellIdentifier)
}
func configureTableView() {
@ -54,7 +53,7 @@ class SurveyListViewController: UIViewController {
func populateQuestionnaireList() {
let questionnaireConverter = FHIRtoRKConverter()
let questionnaireConverter = FhirToResearchKitConverter()
let ed = ExternalStoreDelegate()
@ -68,32 +67,32 @@ class SurveyListViewController: UIViewController {
var counter = 0
for task in tasks! {
let questionnaireId = task.basedOn?[0].reference?.string
questionnaireConverter.extractSteps(reference: questionnaireId!, task: task) { (questionnaire, error) in
DispatchQueue.main.async {
if questionnaire != nil {
if questionnaire!.FHIRtask.status?.rawValue != "completed" {
self.todoQList.append(questionnaire!)
} else {
self.completeQList.append(questionnaire!)
DispatchQueue.main.async {
if questionnaire != nil {
if questionnaire!.FHIRtask.status?.rawValue != "completed" {
self.todoQList.append(questionnaire!)
} else {
self.completeQList.append(questionnaire!)
}
}
counter += 1
if counter == tasks?.count {
self.createQListCategories(todoQ: self.todoQList, completeQ: self.completeQList)
self.configureTableView()
self.surveyListLoadingIndicator.isHidden = true
}
}
counter += 1
if counter == tasks?.count {
self.createQListCategories(todoQ: self.todoQList, completeQ: self.completeQList)
self.configureTableView()
self.surveyListLoadingIndicator.isHidden = true
}
}
}
}
}
}
@ -124,14 +123,14 @@ class SurveyListViewController: UIViewController {
@IBOutlet weak var surveyListLoadingIndicator: UIActivityIndicatorView!
func surveySelected(tagNum: Int) {
let fhirToRk = FHIRtoRKConverter()
let FhirToResearchKit = FhirToResearchKitConverter()
let questionnaire = SurveyListViewController.questionnaireList[tagNum]
let surveyTask = ORKOrderedTask(identifier: title ?? "Questionnaire", steps: fhirToRk.getORKStepsFromQuestionnaire(questionnaire: questionnaire!.FHIRquestionnaire))
let surveyTask = ORKOrderedTask(identifier: title ?? "Questionnaire", steps: FhirToResearchKit.getORKStepsFromQuestionnaire(questionnaire: questionnaire!.FHIRquestionnaire))
let taskViewController = ORKTaskViewController(task: surveyTask, taskRun: nil)
taskViewController.delegate = self
FHIRtoRKConverter.currentIndex = tagNum
FhirToResearchKitConverter.currentIndex = tagNum
self.present(taskViewController, animated: true, completion: nil)
}
}
@ -143,7 +142,7 @@ extension SurveyListViewController: UITableViewDelegate, UITableViewDataSource {
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: Cells.buttonCell, for: indexPath) as? CustomTableViewCell else {fatalError("Unable to create cell")}
guard let cell = tableView.dequeueReusableCell(withIdentifier: QuestionnaireListTableViewCell.buttonCellIdentifier, for: indexPath) as? QuestionnaireListTableViewCell else {fatalError("Unable to create cell")}
let questionnaire = SurveyListViewController.QList[indexPath.section].questionnairesDisplayed?[indexPath.row]
cell.set(questionnaire: questionnaire!)
@ -199,13 +198,13 @@ extension SurveyListViewController: ORKTaskViewControllerDelegate {
}
fileprivate func persistResultsAsQResponse (_ taskViewController: ORKTaskViewController) {
let questionnaireConverter = RKtoFHIRConverter()
let questionnaireConverter = ResearchKitToFhirConverter()
// convert the questionnaire response from ResearchKit type to FHIR QuestionnaireResponse resource
let FHIRQuestionnaireResponse: QuestionnaireResponse = questionnaireConverter.RKQuestionResponseToFHIR(results: taskViewController)
let FHIRQuestionnaireResponse: QuestionnaireResponse = questionnaireConverter.researchKitQuestionResponseToFhir(results: taskViewController)
// set the questionnaireResponse's associated questionnaire
FHIRQuestionnaireResponse.questionnaire = FHIRCanonical((SurveyListViewController.questionnaireList[FHIRtoRKConverter.currentIndex]!.FHIRtask.basedOn?[0].reference?.string)!)
FHIRQuestionnaireResponse.questionnaire = FHIRCanonical((SurveyListViewController.questionnaireList[FhirToResearchKitConverter.currentIndex]!.FHIRtask.basedOn?[0].reference?.string)!)
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let smartClient = appDelegate?.smartClient
@ -221,7 +220,7 @@ extension SurveyListViewController: ORKTaskViewControllerDelegate {
fileprivate func updateTaskStatus(_ taskViewController: ORKTaskViewController) {
// update task completion status in server
let task = SurveyListViewController.questionnaireList[FHIRtoRKConverter.currentIndex]!.FHIRtask
let task = SurveyListViewController.questionnaireList[FhirToResearchKitConverter.currentIndex]!.FHIRtask
task.status = TaskStatus(rawValue: "completed")
task.update(callback: { error in

Просмотреть файл

@ -1,37 +0,0 @@
//
// ViewController.swift
// sampleApp
//
import UIKit
import ResearchKit
import SMART
class ViewController: UIViewController {
var smartClient: Client?
var didAttemptAuthentication = false
override func viewDidLoad() {
super.viewDidLoad()
let appDelegate = UIApplication.shared.delegate as? AppDelegate
smartClient = appDelegate?.smartClient
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if (!didAttemptAuthentication) {
didAttemptAuthentication = true
smartClient?.authorize(callback: { (patient, error) in
print(error)
})
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning();
}
}

Просмотреть файл

@ -1,6 +1,9 @@
//
// ViewControllerBase.swift
// researchKitOnFhir
// ResearchKitOnFhir
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
import Foundation

Просмотреть файл

@ -1,33 +0,0 @@
//
// researchKitOnFhirTests.swift
// researchKitOnFhirTests
//
// Created by admin on 6/23/21.
//
import XCTest
@testable import researchKitOnFhir
class researchKitOnFhirTests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() throws {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() throws {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}

Просмотреть файл

@ -1,42 +0,0 @@
//
// researchKitOnFhirUITests.swift
// researchKitOnFhirUITests
//
// Created by admin on 6/23/21.
//
import XCTest
class researchKitOnFhirUITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests its important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
// Use recording to get started writing UI tests.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testLaunchPerformance() throws {
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
// This measures how long it takes to launch your application.
measure(metrics: [XCTApplicationLaunchMetric()]) {
XCUIApplication().launch()
}
}
}
}