Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions Sources/ResearchKitOnFHIR/FHIRToResearchKit/NavigationRules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,44 @@ extension ORKNavigableOrderedTask {
continue
}

let enableBehavior = item.enableBehavior?.value ?? .all

let allPredicates = try enableWhen.compactMap { try $0.predicate(for: self) }
let predicate: NSPredicate
switch enableBehavior {
case .all:
predicate = .and(allPredicates)
case .any:
predicate = .or(allPredicates)
}
let predicate = try item.predicate(for: items) ?? .or([])
// The translation from FHIR to ResearchKit predicates requires negating the FHIR predicates
// as FHIR predicates activate steps while ResearchKit uses them to skip steps.
self.setSkip(ORKPredicateSkipStepNavigationRule(resultPredicate: .not(predicate)), forStepIdentifier: itemId)
}
}
}

extension QuestionnaireItem {
internal func predicate(for items: [QuestionnaireItem]) throws -> NSPredicate? {
guard let enableWhen else {
return nil
}

let enableBehavior = enableBehavior?.value ?? .all
let allPredicates = try enableWhen.compactMap { try $0.predicate(for: items) }
return switch enableBehavior {
case .all: .and(allPredicates)
case .any: .or(allPredicates)
}
}
}


extension QuestionnaireItemEnableWhen {
/// The enableWhen, as a `NSPredicate`.
/// - Note: This predicate will evaluate to true if the item should be enabled.
/// When using it with e.g. ResearchKit, you will typically need to negate it, since in that context
/// predicates are used mainly to determine when a step should be skipped (i.e., disabled).
fileprivate func predicate(for task: ORKNavigableOrderedTask) throws -> NSPredicate? {
fileprivate func predicate(for items: [QuestionnaireItem]) throws -> NSPredicate? {
guard let enableQuestionId = question.value?.string,
let fhirOperator = `operator`.value else {
return nil
}
let formSteps = task.steps.compactMap { $0 as? ORKFormStep }
let stepIdentifier = formSteps
.first { $0.formItems?.contains(where: { $0.identifier == enableQuestionId }) != nil }?
.identifier

let stepIdentifier = items
.first { $0.item?.contains(where: { $0.linkId.value?.string == enableQuestionId }) != nil }?
.linkId.value?.string
let resultSelector = ORKResultSelector(stepIdentifier: stepIdentifier, resultIdentifier: enableQuestionId)
switch answer {
case .coding(let coding):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ extension QuestionnaireItem {

if question.type == .display {
let formItem = ORKFormItem(sectionTitle: questionText, detailText: question.placeholderText, learnMoreItem: nil, showsProgress: false)
let predicate = try? question.predicate(for: [self])
formItem.visibilityRule = predicate.map { ORKPredicateFormItemVisibilityRule(predicate: $0) }
formItems.append(formItem)
} else if let answerFormat = try? question.toORKAnswerFormat(valueSets: valueSets) {
let formItem = ORKFormItem(identifier: questionId, text: questionText, answerFormat: answerFormat)
Expand Down
Loading