Skip to content

Commit

Permalink
feat: All OCKOutcomeQuery sorting (#22)
Browse files Browse the repository at this point in the history
* feat: All OCKOutcomeQuery sorting

* effectiveDate ascending should be false for all single queries

* add unit tests
  • Loading branch information
cbaker6 authored Mar 3, 2025
1 parent 419401d commit ada038c
Show file tree
Hide file tree
Showing 16 changed files with 64 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ extension OCKStore {
switch order {
case .effectiveDate(let ascending): return NSSortDescriptor(keyPath: \OCKCDCarePlan.effectiveDate, ascending: ascending)
case .title(let ascending): return NSSortDescriptor(keyPath: \OCKCDCarePlan.title, ascending: ascending)
case .groupIdentifier(let ascending): return NSSortDescriptor(keyPath: \OCKCDCarePlan.groupIdentifier, ascending: ascending)
}
} + query.defaultSortDescriptors()
}
Expand Down
1 change: 1 addition & 0 deletions CareKitStore/CareKitStore/CoreData/OCKStore+Contacts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ extension OCKStore {
case .effectiveDate(ascending: let ascending): return NSSortDescriptor(keyPath: \OCKCDContact.effectiveDate, ascending: ascending)
case .familyName(ascending: let ascending): return NSSortDescriptor(keyPath: \OCKCDContact.name.familyName, ascending: ascending)
case .givenName(ascending: let ascending): return NSSortDescriptor(keyPath: \OCKCDContact.name.givenName, ascending: ascending)
case .groupIdentifier(let ascending): return NSSortDescriptor(keyPath: \OCKCDContact.groupIdentifier, ascending: ascending)
}
} + query.defaultSortDescriptors()
}
Expand Down
7 changes: 6 additions & 1 deletion CareKitStore/CareKitStore/CoreData/OCKStore+Outcomes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,12 @@ extension OCKStore {
}

private func buildSortDescriptors(for query: OCKOutcomeQuery) -> [NSSortDescriptor] {
query.defaultSortDescriptors()
query.sortDescriptors.map { order -> NSSortDescriptor in
switch order {
case .effectiveDate(let ascending): return NSSortDescriptor(keyPath: \OCKCDOutcome.effectiveDate, ascending: ascending)
case .groupIdentifier(let ascending): return NSSortDescriptor(keyPath: \OCKCDOutcome.groupIdentifier, ascending: ascending)
}
} + query.defaultSortDescriptors()
}

private func doesEventForOutcomeOccur(in interval: DateInterval) -> NSPredicate {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,14 @@ extension OCKHealthKitPassthroughStore {
taskQuery.ids = outcomeQuery.taskIDs
taskQuery.remoteIDs = outcomeQuery.taskRemoteIDs
taskQuery.uuids = outcomeQuery.taskUUIDs
taskQuery.sortDescriptors = outcomeQuery.sortDescriptors.map { descriptor in
switch descriptor {
case .effectiveDate(ascending: let ascending):
return OCKTaskQuery.SortDescriptor.effectiveDate(ascending: ascending)
case .groupIdentifier(ascending: let ascending):
return OCKTaskQuery.SortDescriptor.groupIdentifier(ascending: ascending)
}
}

return taskQuery
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public extension OCKAnyReadOnlyCarePlanStore {
completion: @escaping OCKResultClosure<OCKAnyCarePlan>) {
var query = OCKCarePlanQuery(for: Date())
query.limit = 1
query.sortDescriptors = [.effectiveDate(ascending: true)]
query.sortDescriptors = [.effectiveDate(ascending: false)]
query.ids = [id]

fetchAnyCarePlans(query: query, callbackQueue: callbackQueue, completion:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public extension OCKReadableCarePlanStore {
func fetchCarePlan(withID id: String, callbackQueue: DispatchQueue = .main, completion: @escaping OCKResultClosure<Plan>) {
var query = OCKCarePlanQuery(for: Date())
query.limit = 1
query.sortDescriptors = [.effectiveDate(ascending: true)]
query.sortDescriptors = [.effectiveDate(ascending: false)]
query.ids = [id]

fetchCarePlans(query: query, callbackQueue: callbackQueue, completion:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public extension OCKAnyReadOnlyContactStore {
completion: @escaping OCKResultClosure<OCKAnyContact>) {
var query = OCKContactQuery(for: Date())
query.limit = 1
query.sortDescriptors = [.effectiveDate(ascending: true)]
query.sortDescriptors = [.effectiveDate(ascending: false)]
query.ids = [id]

fetchAnyContacts(query: query, callbackQueue: callbackQueue, completion:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public extension OCKReadableContactStore {
var query = OCKContactQuery(for: Date())
query.limit = 1
query.ids = [id]
query.sortDescriptors = [.effectiveDate(ascending: true)]
query.sortDescriptors = [.effectiveDate(ascending: false)]

fetchContacts(query: query, callbackQueue: callbackQueue, completion:
chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No contact with matching ID")))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public extension OCKAnyReadOnlyPatientStore {
completion: @escaping OCKResultClosure<OCKAnyPatient>) {
var query = OCKPatientQuery(for: Date())
query.limit = 1
query.sortDescriptors = [.effectiveDate(ascending: true)]
query.sortDescriptors = [.effectiveDate(ascending: false)]
query.ids = [id]

fetchAnyPatients(query: query, callbackQueue: callbackQueue, completion:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public extension OCKReadablePatientStore {
var query = OCKPatientQuery(for: Date())
query.limit = 1
query.ids = [id]
query.sortDescriptors = [.effectiveDate(ascending: true)]
query.sortDescriptors = [.effectiveDate(ascending: false)]

fetchPatients(query: query, callbackQueue: callbackQueue, completion:
chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No patient with matching ID")))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public protocol OCKTaskStore: OCKReadableTaskStore, OCKAnyTaskStore {
public extension OCKReadableTaskStore {
func fetchTask(withID id: String, callbackQueue: DispatchQueue = .main, completion: @escaping OCKResultClosure<Task>) {
var query = OCKTaskQuery(for: Date())
query.sortDescriptors = [.effectiveDate(ascending: true)]
query.sortDescriptors = [.effectiveDate(ascending: false)]
query.ids = [id]
query.limit = 1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,13 @@ extension OCKStoreCoordinator {
$0.anyOutcomes(matching: query)
}

let sortDescriptor = NSSortDescriptor(
keyPath: \OCKCDOutcome.id,
ascending: true
)
let sortDescriptors = query
.sortDescriptors
.map(\.nsSortDescriptor)

let outcomes = combineMany(
sequences: outcomesStreams,
sortingElementsUsing: [sortDescriptor]
sortingElementsUsing: sortDescriptors
)

return outcomes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,16 @@ public struct OCKCarePlanQuery: Equatable, OCKQueryProtocol {

case title(ascending: Bool)
case effectiveDate(ascending: Bool)
case groupIdentifier(ascending: Bool)

var nsSortDescriptor: NSSortDescriptor {
switch self {
case let .effectiveDate(ascending):
return NSSortDescriptor(keyPath: \OCKCDCarePlan.effectiveDate, ascending: ascending)
case let .title(ascending):
return NSSortDescriptor(keyPath: \OCKCDCarePlan.title, ascending: ascending)
case let .groupIdentifier(ascending):
return NSSortDescriptor(keyPath: \OCKCDCarePlan.groupIdentifier, ascending: ascending)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,18 @@ public struct OCKContactQuery: Equatable, OCKQueryProtocol {
case givenName(ascending: Bool)
case familyName(ascending: Bool)
case effectiveDate(ascending: Bool)
case groupIdentifier(ascending: Bool)

var nsSortDescriptor: NSSortDescriptor {
switch self {
case let .effectiveDate(ascending):
return NSSortDescriptor(keyPath: \OCKCDContact.effectiveDate, ascending: ascending)
case let .givenName(ascending):
return NSSortDescriptor(keyPath: \OCKCDContact.name.givenName, ascending: ascending)
case let .familyName(ascending):
return NSSortDescriptor(keyPath: \OCKCDContact.name.familyName, ascending: ascending)
case let .effectiveDate(ascending):
return NSSortDescriptor(keyPath: \OCKCDContact.effectiveDate, ascending: ascending)
case let .groupIdentifier(ascending):
return NSSortDescriptor(keyPath: \OCKCDContact.groupIdentifier, ascending: ascending)
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions CareKitStore/CareKitStore/Structs/Queries/OCKOutcomeQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ import Foundation
/// A query that limits which outcomes will be returned when fetching.
public struct OCKOutcomeQuery: Equatable, OCKQueryProtocol {

/// Specifies the order in which query results will be sorted.
public enum SortDescriptor: Equatable {

case effectiveDate(ascending: Bool)
case groupIdentifier(ascending: Bool)

var nsSortDescriptor: NSSortDescriptor {
switch self {
case let .effectiveDate(ascending):
return NSSortDescriptor(keyPath: \OCKCDOutcome.effectiveDate, ascending: ascending)
case let .groupIdentifier(ascending):
return NSSortDescriptor(keyPath: \OCKCDOutcome.groupIdentifier, ascending: ascending)
}
}
}

/// An array of task identifiers to match against.
public var taskIDs: [String] = []

Expand All @@ -42,6 +58,9 @@ public struct OCKOutcomeQuery: Equatable, OCKQueryProtocol {
/// An array of remote IDs of tasks for which outcomes should be returned.
public var taskRemoteIDs: [String] = []

/// The order in which the results will be sorted when returned from the query.
public var sortDescriptors: [SortDescriptor] = []

// MARK: OCKQuery
public var ids: [String] = []
public var uuids: [UUID] = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class TestHealthKitPassthroughStoreOutcomes: XCTestCase {
XCTAssertEqual(taskQuery.ids, outcomeTaskQuery.taskIDs)
XCTAssertEqual(taskQuery.remoteIDs, outcomeTaskQuery.taskRemoteIDs)
XCTAssertEqual(taskQuery.uuids, outcomeTaskQuery.taskUUIDs)
XCTAssertTrue(taskQuery.sortDescriptors.isEmpty)
}

func testTaskQueryPropertiesAdoptsOutcomeQueryProperties() async throws {
Expand All @@ -177,12 +178,21 @@ class TestHealthKitPassthroughStoreOutcomes: XCTestCase {
outcomeTaskQuery.taskIDs = ["id"]
outcomeTaskQuery.taskRemoteIDs = ["remoteID"]
outcomeTaskQuery.taskUUIDs = [UUID()]
outcomeTaskQuery.sortDescriptors = [
.effectiveDate(ascending: true),
.groupIdentifier(ascending: true)
]
let taskQuery = passthroughStore.makeTaskQuery(from: outcomeTaskQuery)
let expectedTaskSortDescriptors: [OCKTaskQuery.SortDescriptor] = [
.effectiveDate(ascending: true),
.groupIdentifier(ascending: true)
]

XCTAssertEqual(taskQuery.dateInterval, outcomeTaskQuery.dateInterval)
XCTAssertEqual(taskQuery.ids, outcomeTaskQuery.taskIDs)
XCTAssertEqual(taskQuery.remoteIDs, outcomeTaskQuery.taskRemoteIDs)
XCTAssertEqual(taskQuery.uuids, outcomeTaskQuery.taskUUIDs)
XCTAssertEqual(taskQuery.sortDescriptors, expectedTaskSortDescriptors)
}

// MARK: - Utilities
Expand Down

0 comments on commit ada038c

Please sign in to comment.