From 47bb27af4e76a14185f641ec7465b5684dc5d8fa Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Mon, 24 Oct 2016 09:59:34 -0400 Subject: [PATCH 01/15] Ported CDAKit to Swift 3. Used Swift 3 migrator build into Xcode 8, and wherever possible let the migrator do its job and left that source changed intact. When the swift code continued to fail compilation, fixed in place. Ported the test cases to Swift 3. In some cases needed to customize code fixes where Swift 3 is broke, or Xcode 8 is broke. Utilized Xcode 8.1 beta 3 version to get the most up to date compiler changes. For external pods: GRMustache.swift -> using the Swift3 branch (as its not completed and merged to master yet), Fuzi (latest master is Swift 3, but including all commits after latest release build), Try (unchanged) --- CDAKit.xcodeproj/project.pbxproj | 58 ++- .../CDAKitHealthKitBridge.swift | 196 ++++---- .../lib/export/HDSExport.swift | 4 +- .../lib/export/view_helper.swift | 55 ++- .../lib/import/bulk_record_importer.swift | 30 +- .../import/c32/c32_care_goal_importer.swift | 4 +- .../import/c32/c32_condition_importer.swift | 8 +- .../c32/c32_immunization_importer.swift | 4 +- .../c32/c32_insurance_provider_importer.swift | 14 +- .../lib/import/c32/c32_patient_importer.swift | 26 +- .../lib/import/cat1/cat1_header.swift | 38 +- .../import/ccda/ccda_patient_importer.swift | 4 +- .../lib/import/cda/cda_allergy_importer.swift | 2 +- .../import/cda/cda_condition_importer.swift | 8 +- .../import/cda/cda_encounter_importer.swift | 18 +- .../lib/import/cda/cda_entry_finder.swift | 4 +- .../cda/cda_locatable_import_utils.swift | 4 +- .../cda/cda_medical_equipment_importer.swift | 12 +- .../import/cda/cda_medication_importer.swift | 18 +- .../cda/cda_narrative_reference_handler.swift | 5 +- .../cda/cda_organization_importer.swift | 2 +- .../import/cda/cda_procedure_importer.swift | 14 +- .../import/cda/cda_provider_importer.swift | 12 +- .../lib/import/cda/cda_result_importer.swift | 8 +- .../lib/import/cda/cda_section_importer.swift | 60 +-- .../lib/import/provider_import_utils.swift | 16 +- .../lib/models/address.swift | 36 +- .../lib/models/allergy.swift | 14 +- .../lib/models/care_goal.swift | 10 +- .../lib/models/cda_identifier.swift | 20 +- .../lib/models/coded_result_value.swift | 14 +- .../lib/models/communication.swift | 6 +- .../lib/models/condition.swift | 56 +-- .../lib/models/date_shiftable.swift | 2 +- .../lib/models/encounter.swift | 50 +- .../lib/models/entry.swift | 160 ++++--- .../lib/models/entry_detail.swift | 30 +- .../lib/models/facility.swift | 16 +- .../lib/models/family_history.swift | 12 +- .../lib/models/fulfillment_history.swift | 32 +- .../lib/models/functional_status.swift | 12 +- .../lib/models/guarantor.swift | 14 +- .../lib/models/immunization.swift | 22 +- .../lib/models/insurance_provider.swift | 38 +- .../lib/models/lab_result.swift | 30 +- .../lib/models/medical_equipment.swift | 26 +- .../lib/models/medication.swift | 112 ++--- .../lib/models/order_information.swift | 30 +- .../lib/models/organization.swift | 22 +- .../lib/models/person.swift | 28 +- .../physical_quantity_result_value.swift | 20 +- .../lib/models/procedure.swift | 50 +- .../lib/models/provider.swift | 77 +-- .../lib/models/provider_performance.swift | 26 +- .../lib/models/provider_preference.swift | 4 +- .../lib/models/qrda/CDAKQRDAAuthor.swift | 30 +- .../lib/models/qrda/CDAKQRDACustodian.swift | 16 +- .../lib/models/qrda/CDAKQRDADevice.swift | 12 +- .../lib/models/qrda/CDAKQRDAHeader.swift | 32 +- .../qrda/CDAKQRDALegalAuthenticator.swift | 30 +- .../lib/models/reason.swift | 4 +- .../lib/models/record.swift | 306 ++++++------ .../lib/models/reference.swift | 26 +- .../lib/models/result_value.swift | 20 +- .../lib/models/social_history.swift | 2 +- .../lib/models/support.swift | 42 +- .../lib/models/telecom.swift | 26 +- .../lib/models/thing_with_codes.swift | 19 +- .../lib/models/transfer.swift | 14 +- .../lib/models/treating_provider.swift | 8 +- .../lib/models/vital_sign.swift | 6 +- .../lib/util/code_system_helper.swift | 15 +- .../lib/util/hl7_helper.swift | 82 +++- .../swift_helpers/CDAKCodedEntries.swift | 451 ++++++++++++++++-- .../swift_helpers/CDAKCommonUtility.swift | 92 ++-- .../swift_helpers/CDAKGlobalData.swift | 12 +- .../swift_helpers/CDAKJSONInstantiable.swift | 2 +- .../swift_helpers/CDAKUtility.swift | 46 +- .../swift_helpers/CDAKValueAndUnit.swift | 4 +- .../swift_helpers/Dictionary+Extensions.swift | 6 +- .../swift_helpers/Mustache+Filters.swift | 23 +- .../swift_helpers/NSDate+Formatters.swift | 92 ++-- .../NSObject+PropertyNames.swift | 12 +- .../swift_helpers/String+Extensions.swift | 23 +- CDAKitTests/BasicXPathTest.swift | 3 +- CDAKitTests/CDAProviderImporterTest.swift | 4 +- CDAKitTests/DateShiftTest.swift | 2 +- CDAKitTests/EntryTest.swift | 10 +- CDAKitTests/GRMustacheTest.swift | 70 +-- CDAKitTests/HL7HelperTest.swift | 30 +- CDAKitTests/HealthKitRecordTest.swift | 28 +- CDAKitTests/RecordTestElements.swift | 56 +-- CDAKitTests/TestHelpers.swift | 14 +- CDAKitTests/ViewHelperTest.swift | 10 +- Podfile | 16 +- 95 files changed, 1936 insertions(+), 1353 deletions(-) diff --git a/CDAKit.xcodeproj/project.pbxproj b/CDAKit.xcodeproj/project.pbxproj index b6a7672..212b4bb 100644 --- a/CDAKit.xcodeproj/project.pbxproj +++ b/CDAKit.xcodeproj/project.pbxproj @@ -331,7 +331,7 @@ 38359E051C7B5DD400CCC036 /* c32_performer.c32.mustache */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = c32_performer.c32.mustache; sourceTree = ""; }; 38359E071C7B774400CCC036 /* CDAKit.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CDAKit.podspec; sourceTree = ""; }; 38359E081C7B774400CCC036 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; - 38359E091C7B774400CCC036 /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = ""; }; + 38359E091C7B774400CCC036 /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 384E23101C737A8C009B9DED /* 170.314(b)(1)InPt_Discharge Summary CED Type.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "170.314(b)(1)InPt_Discharge Summary CED Type.xml"; sourceTree = ""; }; 384E23131C738E4E009B9DED /* CDAKJSONInstantiable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CDAKJSONInstantiable.swift; sourceTree = ""; }; 384E23161C73C517009B9DED /* MetadataImporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetadataImporter.swift; sourceTree = ""; }; @@ -1348,12 +1348,12 @@ isa = PBXNativeTarget; buildConfigurationList = 389170451C6CC1EE00A31299 /* Build configuration list for PBXNativeTarget "CDAKit" */; buildPhases = ( - 121123786CCEF5344AF26C54 /* Check Pods Manifest.lock */, + 121123786CCEF5344AF26C54 /* [CP] Check Pods Manifest.lock */, 3891702C1C6CC1EE00A31299 /* Sources */, 3891702D1C6CC1EE00A31299 /* Frameworks */, 3891702E1C6CC1EE00A31299 /* Headers */, 3891702F1C6CC1EE00A31299 /* Resources */, - 3414E6FD4CA7A95F5ADAA642 /* Copy Pods Resources */, + 3414E6FD4CA7A95F5ADAA642 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1368,12 +1368,12 @@ isa = PBXNativeTarget; buildConfigurationList = 389170481C6CC1EE00A31299 /* Build configuration list for PBXNativeTarget "CDAKitTests" */; buildPhases = ( - E3D409D33B05989FC3BC310B /* Check Pods Manifest.lock */, + E3D409D33B05989FC3BC310B /* [CP] Check Pods Manifest.lock */, 389170371C6CC1EE00A31299 /* Sources */, 389170381C6CC1EE00A31299 /* Frameworks */, 389170391C6CC1EE00A31299 /* Resources */, - 96FF48670B856178CE4C0B16 /* Embed Pods Frameworks */, - 604FE589373D3447785062B5 /* Copy Pods Resources */, + 96FF48670B856178CE4C0B16 /* [CP] Embed Pods Frameworks */, + 604FE589373D3447785062B5 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1392,14 +1392,17 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Eric Whitley"; TargetAttributes = { 389170301C6CC1EE00A31299 = { CreatedOnToolsVersion = 7.2.1; + LastSwiftMigration = 0800; }; 3891703A1C6CC1EE00A31299 = { CreatedOnToolsVersion = 7.2.1; + DevelopmentTeam = E22XJ7D3WH; + LastSwiftMigration = 0800; }; }; }; @@ -1584,29 +1587,29 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 121123786CCEF5344AF26C54 /* Check Pods Manifest.lock */ = { + 121123786CCEF5344AF26C54 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Check Pods Manifest.lock"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; - 3414E6FD4CA7A95F5ADAA642 /* Copy Pods Resources */ = { + 3414E6FD4CA7A95F5ADAA642 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -1614,14 +1617,14 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CDAKit/Pods-CDAKit-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 604FE589373D3447785062B5 /* Copy Pods Resources */ = { + 604FE589373D3447785062B5 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -1629,14 +1632,14 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CDAKitTests/Pods-CDAKitTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 96FF48670B856178CE4C0B16 /* Embed Pods Frameworks */ = { + 96FF48670B856178CE4C0B16 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Embed Pods Frameworks"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -1644,19 +1647,19 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CDAKitTests/Pods-CDAKitTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - E3D409D33B05989FC3BC310B /* Check Pods Manifest.lock */ = { + E3D409D33B05989FC3BC310B /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Check Pods Manifest.lock"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -1854,8 +1857,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -1902,8 +1907,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -1923,6 +1930,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1934,6 +1942,8 @@ isa = XCBuildConfiguration; baseConfigurationReference = E4B275D491AE4CABC47FF7B2 /* Pods-CDAKit.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1945,6 +1955,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -1952,6 +1963,8 @@ isa = XCBuildConfiguration; baseConfigurationReference = 5440B6F09B325B25FC518484 /* Pods-CDAKit.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1963,6 +1976,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -1970,10 +1984,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = B3721CB6B043AD64FC0ED757 /* Pods-CDAKitTests.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + DEVELOPMENT_TEAM = E22XJ7D3WH; INFOPLIST_FILE = CDAKitTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = ericwhitley.org.CDAKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -1981,10 +1998,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 3584B78321E453821B9F825B /* Pods-CDAKitTests.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + DEVELOPMENT_TEAM = E22XJ7D3WH; INFOPLIST_FILE = CDAKitTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = ericwhitley.org.CDAKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift b/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift index 16a3323..0601f36 100644 --- a/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift +++ b/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift @@ -59,18 +59,18 @@ Provides HealthKit bridging with CDA structures. */ -public class CDAKHealthKitBridge { +open class CDAKHealthKitBridge { //MARK: Primary Singleton accessor /** Singleton for all shared properties and methods. */ - public static let sharedInstance = CDAKHealthKitBridge() + open static let sharedInstance = CDAKHealthKitBridge() /** Primary class initializer - PRIVATE */ - private init() { + fileprivate init() { loadDefaultHealthKitTermMap() loadDefaultHKQuantityTypeInfo() } @@ -100,7 +100,7 @@ public class CDAKHealthKitBridge { ``` */ - public var CDAKHKQuantityTypeDescriptions: [String:String] = [:] + open var CDAKHKQuantityTypeDescriptions: [String:String] = [:] // placeholder for preferredUnitsForQuantityTypes from user's HealthKitStore // https://developer.apple.com/library/prerelease/ios/documentation/HealthKit/Reference/HKHealthStore_Class/index.html#//apple_ref/occ/instm/HKHealthStore/preferredUnitsForQuantityTypes:completion: /** @@ -123,7 +123,7 @@ public class CDAKHealthKitBridge { [preferredUnitsForQuantityTypes](https://developer.apple.com/library/prerelease/ios/documentation/HealthKit/Reference/HKHealthStore_Class/index.html#//apple_ref/occ/instm/HKHealthStore/preferredUnitsForQuantityTypes:completion:) */ - public var CDAKHKQuantityTypeDefaultUnits: [CDAKHKQuantityIdentifiers:String] = [:] + open var CDAKHKQuantityTypeDefaultUnits: [CDAKHKQuantityIdentifiers:String] = [:] /** Default classification for a specified quantity type identifier. @@ -148,7 +148,7 @@ public class CDAKHealthKitBridge { ``` */ - public var CDAKHKQuantityTypeDefaultTypes: [String:String] = [:] + open var CDAKHKQuantityTypeDefaultTypes: [String:String] = [:] //MARK: Convenience Enumerations @@ -203,12 +203,12 @@ public class CDAKHealthKitBridge { - func dateFromEvent(eventDate: Double) -> NSDate + func dateFromEvent(_ eventDate: Double) -> Date { - return NSDate(timeIntervalSince1970: NSTimeInterval(eventDate)) + return Date(timeIntervalSince1970: TimeInterval(eventDate)) } - func dateFromEvent(eventDate: NSDate) -> Double + func dateFromEvent(_ eventDate: Date) -> Double { return eventDate.timeIntervalSince1970 } @@ -229,7 +229,7 @@ public class CDAKHealthKitBridge { ``` */ - public func administrativeGender(biologicalSex:HKBiologicalSex?)-> (code:String, displayName:String) + open func administrativeGender(_ biologicalSex:HKBiologicalSex?)-> (code:String, displayName:String) { @@ -239,10 +239,10 @@ public class CDAKHealthKitBridge { if biologicalSex != nil { switch( biologicalSex! ) { - case .Female: + case .female: genderCode = "F" genderDisplayName = "Female" - case .Male: + case .male: genderCode = "M" genderDisplayName = "Male" default: @@ -267,37 +267,37 @@ public class CDAKHealthKitBridge { ``` ``` - */ public func administrativeGender(genderCode:String?)-> HKBiologicalSex + */ open func administrativeGender(_ genderCode:String?)-> HKBiologicalSex { if let genderCode = genderCode { switch genderCode { case "M": - return HKBiologicalSex.Male + return HKBiologicalSex.male case "F": - return HKBiologicalSex.Female + return HKBiologicalSex.female case "UN": if #available(iOS 8.2, *) { - return HKBiologicalSex.Other + return HKBiologicalSex.other } else { print("Gender for code: \(genderCode) not supported on this version of iOS") } default: print("Indeterminate biological gender for code: \(genderCode)") if #available(iOS 8.2, *) { - return HKBiologicalSex.Other + return HKBiologicalSex.other } else { // Fallback on earlier versions } } } - return HKBiologicalSex.NotSet + return HKBiologicalSex.notSet } - func getDatesForResult(entry: CDAKEntry, value: CDAKResultValue) -> (start_date: NSDate?, end_date: NSDate?) { + func getDatesForResult(_ entry: CDAKEntry, value: CDAKResultValue) -> (start_date: Date?, end_date: Date?) { - var start_date: NSDate? - var end_date: NSDate? + var start_date: Date? + var end_date: Date? let start_date_dbl: Double? = value.start_time ?? value.time ?? entry.start_time ?? entry.time let end_date_dbl: Double? = value.end_time ?? value.time ?? entry.end_time ?? entry.time @@ -327,9 +327,9 @@ public class CDAKHealthKitBridge { - parameter withHKMetadata: [String:AnyObject] - Custom metadata you may wish to apply to HealthKit samples */ - public func sampleForEntry(entry: CDAKEntry, forSampleType sampleType: CDAKHKQuantityIdentifiers? = nil, withHKMetadata meta: [String:AnyObject] = [:]) -> HKQuantitySample? { + open func sampleForEntry(_ entry: CDAKEntry, forSampleType sampleType: CDAKHKQuantityIdentifiers? = nil, withHKMetadata meta: [String:AnyObject] = [:]) -> HKQuantitySample? { - print("evaluating entry \(entry.dynamicType) with codes \(entry.codes) and value \(entry.values.first)") + print("evaluating entry \(type(of: entry)) with codes \(entry.codes) and value \(entry.values.first)") if let sampleType = sampleType { return sampleForEntryValue(entry, allowedCodeList: @@ -347,19 +347,20 @@ public class CDAKHealthKitBridge { } - func sampleForEntryValue(entry: CDAKEntry, allowedCodeList: CDAKCodedEntries?, quantityTypeIdentifier: String, var withHKMetadata meta: [String:AnyObject] = [:]) -> HKQuantitySample? { + func sampleForEntryValue(_ entry: CDAKEntry, allowedCodeList: CDAKCodedEntries?, quantityTypeIdentifier: String, withHKMetadata meta: [String:AnyObject] = [:]) -> HKQuantitySample? { + var meta = meta if let allowedCodeList = allowedCodeList { - if let matching_codes = entry.codes.findIntersectingCodedEntries(forCodedEntries: allowedCodeList) where matching_codes.count > 0 { + if let matching_codes = entry.codes.findIntersectingCodedEntries(forCodedEntries: allowedCodeList) , matching_codes.count > 0 { //we have a matching code reference, so let's go ahead and try to return this entry if let r_val = entry.values.first as? CDAKPhysicalQuantityResultValue { let times = getDatesForResult(entry, value: r_val) - if let scalar = r_val.scalar, hr = Double(scalar), start_date = times.start_date, end_date = times.end_date, unit = unitForCDAString(r_val.units, forQuantityTypeIdentifier: quantityTypeIdentifier) { - if let qtyType = HKQuantityType.quantityTypeForIdentifier(quantityTypeIdentifier) { - if qtyType.isCompatibleWithUnit(unit) { - meta[CDAKHKMetadataKeys.CDAKMetadataEntryHash.rawValue] = entry.hashValue + if let scalar = r_val.scalar, let hr = Double(scalar), let start_date = times.start_date, let end_date = times.end_date, let unit = unitForCDAString(r_val.units, forQuantityTypeIdentifier: quantityTypeIdentifier) { + if let qtyType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: quantityTypeIdentifier)) { + if qtyType.is(compatibleWith: unit) { + meta[CDAKHKMetadataKeys.CDAKMetadataEntryHash.rawValue] = entry.hashValue as AnyObject? let qty: HKQuantity = HKQuantity(unit: unit, doubleValue: hr) let qtySample: HKQuantitySample = HKQuantitySample(type: qtyType - , quantity: qty, startDate: start_date, endDate: end_date, metadata: meta) + , quantity: qty, start: start_date, end: end_date, metadata: meta) return qtySample } else { print("sampleForEntryValue() - Cannot create sample of type '\(quantityTypeIdentifier)' using unit type '\(unit)'. Unit is not compatible.") @@ -392,7 +393,7 @@ public class CDAKHealthKitBridge { } */ - public var cdaStringUnitFinder : ((unit_string: String?, typeIdentifier: String? ) -> HKUnit?)? + open var cdaStringUnitFinder : ((_ unit_string: String?, _ typeIdentifier: String? ) -> HKUnit?)? /** @@ -410,11 +411,12 @@ public class CDAKHealthKitBridge { - returns: Optional HKUnit. If one can be created, it will be populated. */ - public func unitForCDAString(var unit_string: String?, forQuantityTypeIdentifier typeIdentifier: String? = nil) -> HKUnit? { + public func unitForCDAString(_ unit_string: String?, forQuantityTypeIdentifier typeIdentifier: String? = nil) -> HKUnit? { + var unit_string = unit_string if let cdaStringUnitFinder = cdaStringUnitFinder { - return cdaStringUnitFinder(unit_string: unit_string, typeIdentifier: typeIdentifier) + return cdaStringUnitFinder(unit_string, typeIdentifier) } else { var a_unit: HKUnit? @@ -450,7 +452,7 @@ public class CDAKHealthKitBridge { } - switch a_unit_string.lowercaseString { + switch a_unit_string.lowercased() { case "in_i", "in_us", "inch", "inches": a_unit_string = "in" case "lbs", "lb_av", "pound", "pounds": a_unit_string = "lb" case "F": a_unit_string = "degF" @@ -474,7 +476,7 @@ public class CDAKHealthKitBridge { // and use SwiftyTryCatch here to let us just ... try. do { try trap { - a_unit = HKUnit(fromString: a_unit_string) + a_unit = HKUnit(from: a_unit_string) } } catch let error as NSError { print("unitForCDAString failure for unit '\(unit_string)' - \(error.description) ") @@ -504,11 +506,34 @@ public class CDAKHealthKitBridge { [preferredUnitsForQuantityTypes](https://developer.apple.com/library/prerelease/ios/documentation/HealthKit/Reference/HKHealthStore_Class/index.html#//apple_ref/occ/instm/HKHealthStore/preferredUnitsForQuantityTypes:completion:) */ - public func setCDAKUnitTypesWithUserSettings(store: HKHealthStore) { + open func setCDAKUnitTypesWithUserSettings(_ store: HKHealthStore) { for sampleType in supportedHKQuantityTypes { //doing this one by one as I don't know what happens if we request all identifiers at once and don't have access to a subset if #available(iOS 8.2, *) { - store.preferredUnitsForQuantityTypes(Set([sampleType])) { (preferredUnits: [HKQuantityType : HKUnit], error: NSError?) -> Void in + store.preferredUnits(for: Set([sampleType]), completion: { (preferredUnits, error) in + if error == nil { + if let unit: HKUnit = preferredUnits[sampleType] { + if let id = CDAKHKQuantityIdentifiers(rawValue: sampleType.identifier) { + self.CDAKHKQuantityTypeDefaultUnits[id] = unit.unitString + print("Set default sample unit type for '\(sampleType.identifier)' to '\(unit.unitString)'") + } + } + } else { + if let _error = error as? NSError { + switch _error.code { + case 5: + if let id = CDAKHKQuantityIdentifiers(rawValue: sampleType.identifier) { + print("Access to sample \(sampleType.identifier) denied - using default unit \(self.CDAKHKQuantityTypeDefaultUnits[id])") + } + default: + print("Error accessing user sample types. \(error?.localizedDescription)") + } + } + + } + }) +/* + store.preferredUnits(for: Set([sampleType])) { (preferredUnits: [HKQuantityType : HKUnit], error: NSError?) -> Void in if error == nil { if let unit: HKUnit = preferredUnits[sampleType] { if let id = CDAKHKQuantityIdentifiers(rawValue: sampleType.identifier) { @@ -526,7 +551,7 @@ public class CDAKHealthKitBridge { print("Error accessing user sample types. \(error?.localizedDescription)") } } - } + } */ } else { print("This version of iOS does not support preferredUnitsForQuantityTypes") } @@ -540,16 +565,16 @@ public class CDAKHealthKitBridge { - parameter preferredUnitString: unit string (EX: "cm") - parameter forHKQuantityTypeIdentifier: the type identifier */ - public func setPreferedUnitForSampleType(preferredUnitString unit: String, forHKQuantityTypeIdentifier type: String) { + open func setPreferedUnitForSampleType(preferredUnitString unit: String, forHKQuantityTypeIdentifier type: String) { if let id = CDAKHKQuantityIdentifiers(rawValue: type) { CDAKHKQuantityTypeDefaultUnits[id] = unit } } - private var _supportedHKQuantityTypes: Set? + fileprivate var _supportedHKQuantityTypes: Set? ///Supplies a list of all supported HealthKit quantity types - public var supportedHKQuantityTypes: Set { + open var supportedHKQuantityTypes: Set { get { if _supportedHKQuantityTypes != nil { @@ -558,7 +583,7 @@ public class CDAKHealthKitBridge { var supportedTypes = Set() for identifier in supportedHKQuantityTypeIdentifiers { - if let sampleType = HKQuantityType.quantityTypeForIdentifier(identifier) { + if let sampleType = HKQuantityType.quantityType(forIdentifier: identifier /* HKQuantityTypeIdentifier(rawValue: identifier) */) { supportedTypes.insert(sampleType) } } @@ -567,9 +592,9 @@ public class CDAKHealthKitBridge { } } - private var _supportedHKQuantityTypeIdentifiers: Set? + fileprivate var _supportedHKQuantityTypeIdentifiers: Set? ///Supplies a list of all supported HealthKit sample type identiifers - public var supportedHKQuantityTypeIdentifiers: Set { + open var supportedHKQuantityTypeIdentifiers: Set { get { if _supportedHKQuantityTypeIdentifiers != nil { @@ -577,28 +602,28 @@ public class CDAKHealthKitBridge { } var supportedTypes = Set([ - HKQuantityTypeIdentifierActiveEnergyBurned, HKQuantityTypeIdentifierBasalEnergyBurned, HKQuantityTypeIdentifierBloodAlcoholContent, HKQuantityTypeIdentifierBloodGlucose, HKQuantityTypeIdentifierBloodPressureDiastolic, HKQuantityTypeIdentifierBloodPressureSystolic, HKQuantityTypeIdentifierBodyFatPercentage, HKQuantityTypeIdentifierBodyMass, HKQuantityTypeIdentifierBodyMassIndex, HKQuantityTypeIdentifierBodyTemperature, HKQuantityTypeIdentifierDistanceCycling, HKQuantityTypeIdentifierDistanceWalkingRunning, HKQuantityTypeIdentifierElectrodermalActivity, HKQuantityTypeIdentifierFlightsClimbed, HKQuantityTypeIdentifierForcedExpiratoryVolume1, HKQuantityTypeIdentifierForcedVitalCapacity, HKQuantityTypeIdentifierHeartRate, HKQuantityTypeIdentifierHeight, HKQuantityTypeIdentifierInhalerUsage, HKQuantityTypeIdentifierLeanBodyMass, HKQuantityTypeIdentifierNikeFuel, HKQuantityTypeIdentifierNumberOfTimesFallen, HKQuantityTypeIdentifierOxygenSaturation, HKQuantityTypeIdentifierPeakExpiratoryFlowRate, HKQuantityTypeIdentifierPeripheralPerfusionIndex, HKQuantityTypeIdentifierRespiratoryRate, HKQuantityTypeIdentifierStepCount + HKQuantityTypeIdentifier.activeEnergyBurned, HKQuantityTypeIdentifier.basalEnergyBurned, HKQuantityTypeIdentifier.bloodAlcoholContent, HKQuantityTypeIdentifier.bloodGlucose, HKQuantityTypeIdentifier.bloodPressureDiastolic, HKQuantityTypeIdentifier.bloodPressureSystolic, HKQuantityTypeIdentifier.bodyFatPercentage, HKQuantityTypeIdentifier.bodyMass, HKQuantityTypeIdentifier.bodyMassIndex, HKQuantityTypeIdentifier.bodyTemperature, HKQuantityTypeIdentifier.distanceCycling, HKQuantityTypeIdentifier.distanceWalkingRunning, HKQuantityTypeIdentifier.electrodermalActivity, HKQuantityTypeIdentifier.flightsClimbed, HKQuantityTypeIdentifier.forcedExpiratoryVolume1, HKQuantityTypeIdentifier.forcedVitalCapacity, HKQuantityTypeIdentifier.heartRate, HKQuantityTypeIdentifier.height, HKQuantityTypeIdentifier.inhalerUsage, HKQuantityTypeIdentifier.leanBodyMass, HKQuantityTypeIdentifier.nikeFuel, HKQuantityTypeIdentifier.numberOfTimesFallen, HKQuantityTypeIdentifier.oxygenSaturation, HKQuantityTypeIdentifier.peakExpiratoryFlowRate, HKQuantityTypeIdentifier.peripheralPerfusionIndex, HKQuantityTypeIdentifier.respiratoryRate, HKQuantityTypeIdentifier.stepCount ]) if #available(iOS 9.0, *) { - supportedTypes.insert(HKQuantityTypeIdentifierBasalBodyTemperature) + supportedTypes.insert(HKQuantityTypeIdentifier.basalBodyTemperature) } _supportedHKQuantityTypeIdentifiers = supportedTypes - return supportedTypes + return supportedTypes // as! Set } } - private func getPlistFromBundle(plistNamed name: String) -> NSDictionary? { - if let filePath = CDAKCommonUtility.bundle.pathForResource(name, ofType: "plist"), plistData = NSDictionary(contentsOfFile:filePath) { + fileprivate func getPlistFromBundle(plistNamed name: String) -> NSDictionary? { + if let filePath = CDAKCommonUtility.bundle.path(forResource: name, ofType: "plist"), let plistData = NSDictionary(contentsOfFile:filePath) { return plistData } return nil } - private func loadDefaultHKQuantityTypeInfo() { + fileprivate func loadDefaultHKQuantityTypeInfo() { if let plistData = getPlistFromBundle(plistNamed: "CDAKitDefaultSampleTypeIdentifierSettings") { loadHealthKitQuantityTypeMetadata(withPlist: plistData) } else { @@ -633,10 +658,11 @@ public class CDAKHealthKitBridge { ``` - */ public func loadHealthKitQuantityTypeMetadata(withPlist plist: NSDictionary) { + */ open func loadHealthKitQuantityTypeMetadata(withPlist plist: NSDictionary) { for (identifierKey, entryData) in plist { - if let identifierKey = identifierKey as? String, entryData = entryData as? NSDictionary { - if supportedHKQuantityTypeIdentifiers.contains(identifierKey) { + if let identifierKey = identifierKey as? String, let entryData = entryData as? NSDictionary { + let ident = HKQuantityTypeIdentifier(rawValue: identifierKey) + if supportedHKQuantityTypeIdentifiers.contains(ident) { if let unit = entryData["unit"] as? String { if let id = CDAKHKQuantityIdentifiers(rawValue: identifierKey) { CDAKHKQuantityTypeDefaultUnits[id] = unit @@ -656,7 +682,7 @@ public class CDAKHealthKitBridge { } - private func loadDefaultHealthKitTermMap() { + fileprivate func loadDefaultHealthKitTermMap() { if let plistData = getPlistFromBundle(plistNamed: "CDAKitDefaultHealthKitTermMap") { loadHealthKitTermMap(withPlist: plistData) } else { @@ -696,10 +722,10 @@ public class CDAKHealthKitBridge { ``` */ - public func loadHealthKitTermMap(withPlist plist: NSDictionary) { + open func loadHealthKitTermMap(withPlist plist: NSDictionary) { for (identifierKey, entryData) in plist { //"identifierKey" will be something like "HKQuantityTypeIdentifierBloodGlucose" - if let identifierKey = identifierKey as? String, entryData = entryData as? NSDictionary { + if let identifierKey = identifierKey as? String, let entryData = entryData as? NSDictionary { CDAKHKTypeConceptsImport[identifierKey] = restoreCDAKCodedEntriesFromPList(usingPlist: entryData, forMapDirection: ["import", "both"]) CDAKHKTypeConceptsExport[identifierKey] = restoreCDAKCodedEntriesFromPList(usingPlist: entryData, forMapDirection: ["export", "both"]) } @@ -732,13 +758,13 @@ public class CDAKHealthKitBridge { // } //forMapDirection - > - private func restoreCDAKCodedEntriesFromPList(usingPlist dictEntry: NSDictionary, forMapDirection direction: [String]) -> CDAKCodedEntries { + fileprivate func restoreCDAKCodedEntriesFromPList(usingPlist dictEntry: NSDictionary, forMapDirection direction: [String]) -> CDAKCodedEntries { var codedEntries = CDAKCodedEntries() for (vocabulary, codes) in dictEntry { - if let vocabulary = vocabulary as? String, codes = codes as? [NSDictionary] { + if let vocabulary = vocabulary as? String, let codes = codes as? [NSDictionary] { for a_code in codes { - if let code = a_code["code"] as? String, mapRestriction = a_code["mapRestriction"] as? String { + if let code = a_code["code"] as? String, let mapRestriction = a_code["mapRestriction"] as? String { if direction.contains(mapRestriction) { //we only want to load the codes for a specific import or export set var displayName: String? @@ -773,40 +799,40 @@ public enum CDAKHKMetadataKeys: String { /** Primary bridging record to connect our CDA models with HealthKit */ -public class CDAKHKRecord: CustomStringConvertible { +open class CDAKHKRecord: CustomStringConvertible { //Mark: Basic profile and demographics ///Person's prefix (was Title) - public var prefix: String? + open var prefix: String? ///Person's first / given name - public var first: String? + open var first: String? ///Person's last / family name - public var last: String? + open var last: String? ///Person's name suffix - public var suffix: String? + open var suffix: String? ///Person's biological sex / gender - public var gender: HKBiologicalSex? + open var gender: HKBiologicalSex? ///Birth date - public var birthdate: NSDate? + open var birthdate: Date? ///Deceased date - public var deathdate: NSDate? //probably not interested in this one... + open var deathdate: Date? //probably not interested in this one... ///Effective time of record - public var effective_time: NSDate? + open var effective_time: Date? //Mark: HealthKit samples ///All HealthKit samples - public var samples: [HKQuantitySample] = [] + open var samples: [HKQuantitySample] = [] ///Any metadata you may wish to inject into HealthKit when it samples are created - public var metadata: [String:AnyObject] = [:] + open var metadata: [String:AnyObject] = [:] /** Export this HealthKit-based record to a CDA-based representation This can then be used to add more information or export to CDA XML. */ - public func exportAsCDAKRecord() -> CDAKRecord { + open func exportAsCDAKRecord() -> CDAKRecord { let aRecord = CDAKRecord() aRecord.prefix = prefix @@ -847,7 +873,7 @@ public class CDAKHKRecord: CustomStringConvertible { } - private func setCDAKDataFromSample(sample: HKQuantitySample, forEntry entry: CDAKEntry) { + fileprivate func setCDAKDataFromSample(_ sample: HKQuantitySample, forEntry entry: CDAKEntry) { entry.start_time = sample.startDate.timeIntervalSince1970 entry.end_time = sample.endDate.timeIntervalSince1970 if let codes = CDAKHealthKitBridge.sharedInstance.CDAKHKTypeConceptsExport[sample.sampleType.identifier] { @@ -859,18 +885,18 @@ public class CDAKHKRecord: CustomStringConvertible { } } - private func getCDAKValueFromSample(sample: HKQuantitySample) -> CDAKPhysicalQuantityResultValue? { + fileprivate func getCDAKValueFromSample(_ sample: HKQuantitySample) -> CDAKPhysicalQuantityResultValue? { let sampleType = sample.sampleType.identifier - if let id = CDAKHealthKitBridge.CDAKHKQuantityIdentifiers(rawValue: sampleType), unitString = CDAKHealthKitBridge.sharedInstance.CDAKHKQuantityTypeDefaultUnits[id] { + if let id = CDAKHealthKitBridge.CDAKHKQuantityIdentifiers(rawValue: sampleType), let unitString = CDAKHealthKitBridge.sharedInstance.CDAKHKQuantityTypeDefaultUnits[id] { - let defaultUnit = HKUnit(fromString: unitString) + let defaultUnit = HKUnit(from: unitString) - if sample.quantity.isCompatibleWithUnit(defaultUnit) { - return CDAKPhysicalQuantityResultValue(scalar: sample.quantity.doubleValueForUnit(defaultUnit), units: defaultUnit.unitString) + if sample.quantity.is(compatibleWith: defaultUnit) { + return CDAKPhysicalQuantityResultValue(scalar: sample.quantity.doubleValue(for: defaultUnit), units: defaultUnit.unitString) } else { - print("exportAsCDAKRecord() - Cannot sample values for sample of type '\(HKQuantityTypeIdentifierBodyMassIndex)' using unit type '\(defaultUnit)'") + print("exportAsCDAKRecord() - Cannot sample values for sample of type '\(HKQuantityTypeIdentifier.bodyMassIndex)' using unit type '\(defaultUnit)'") } } @@ -897,13 +923,13 @@ public class CDAKHKRecord: CustomStringConvertible { self.metadata = metadata if let root = patient.header?.identifier?.root { - self.metadata[CDAKHKMetadataKeys.CDAKMetadataRecordIDRoot.rawValue] = root + self.metadata[CDAKHKMetadataKeys.CDAKMetadataRecordIDRoot.rawValue] = root as AnyObject? } //For now we're just going to manually choose which entries we add - samples.appendContentsOf( patient.vital_signs.flatMap( { CDAKHealthKitBridge.sharedInstance.sampleForEntry($0, withHKMetadata: self.metadata)} ) ) - samples.appendContentsOf( patient.results.flatMap( { CDAKHealthKitBridge.sharedInstance.sampleForEntry($0, withHKMetadata: self.metadata)} ) ) - samples.appendContentsOf( patient.procedures.flatMap( { CDAKHealthKitBridge.sharedInstance.sampleForEntry($0, withHKMetadata: self.metadata)} ) ) + samples.append( contentsOf: patient.vital_signs.flatMap( { CDAKHealthKitBridge.sharedInstance.sampleForEntry($0, withHKMetadata: self.metadata)} ) ) + samples.append( contentsOf: patient.results.flatMap( { CDAKHealthKitBridge.sharedInstance.sampleForEntry($0, withHKMetadata: self.metadata)} ) ) + samples.append( contentsOf: patient.procedures.flatMap( { CDAKHealthKitBridge.sharedInstance.sampleForEntry($0, withHKMetadata: self.metadata)} ) ) @@ -925,12 +951,12 @@ public class CDAKHKRecord: CustomStringConvertible { // MARK: Standard properties ///Quick description of the included HealthKit samples - public var samplesDescription : String { - return samples.map({"\($0.sampleType) \($0.description)"}).joinWithSeparator(", ") + open var samplesDescription : String { + return samples.map({"\($0.sampleType) \($0.description)"}).joined(separator: ", ") } ///Debugging description - public var description: String { + open var description: String { return "CDAKHKRecord => prefix: \(prefix), first: \(first), last: \(last), suffix: \(suffix), gender: \(gender), birthdate: \(birthdate), deathdate: \(deathdate), samples: \(samplesDescription) " } diff --git a/CDAKit/health-data-standards/lib/export/HDSExport.swift b/CDAKit/health-data-standards/lib/export/HDSExport.swift index e16593b..11fc31a 100644 --- a/CDAKit/health-data-standards/lib/export/HDSExport.swift +++ b/CDAKit/health-data-standards/lib/export/HDSExport.swift @@ -12,7 +12,7 @@ import Mustache /** Primary CDA export class */ -public class CDAKExport { +open class CDAKExport { /** Provides list of known CDA export types @@ -31,7 +31,7 @@ public class CDAKExport { - parameter record: CDAKRecord you wish to export to XML - parameter format: Specified format (from CDAKExportFormat). (.c32, .ccda) */ - public class func export(patientRecord record: CDAKRecord, inFormat format: CDAKExportFormat) -> String { + open class func export(patientRecord record: CDAKRecord, inFormat format: CDAKExportFormat) -> String { var rendering = "" diff --git a/CDAKit/health-data-standards/lib/export/view_helper.swift b/CDAKit/health-data-standards/lib/export/view_helper.swift index 7bad490..38b0c46 100644 --- a/CDAKit/health-data-standards/lib/export/view_helper.swift +++ b/CDAKit/health-data-standards/lib/export/view_helper.swift @@ -7,6 +7,26 @@ // import Foundation +fileprivate func < (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } +} + +fileprivate func > (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l > r + default: + return rhs < lhs + } +} + class ViewHelper { @@ -14,7 +34,8 @@ class ViewHelper { // {"tag_name"=>"value", "extra_content"=>"xsi:type=\"CD\"", "preferred_code_sets"=>["SNOMED-CT"]} // {"preferred_code_sets"=>["LOINC", "SNOMED-CT"]} // looks like the value of the dictionary can be a string or an array of values - class func code_display(entry: CDAKEntry, var options:[String:Any] = [:]) -> String { + class func code_display(_ entry: CDAKEntry, options:[String:Any] = [:]) -> String { + var options = options if options["tag_name"] == nil { options["tag_name"] = "code" } @@ -99,9 +120,9 @@ class ViewHelper { return code_string } - class func status_code_for(entry: CDAKEntry) -> String? { + class func status_code_for(_ entry: CDAKEntry) -> String? { if let status = entry.status { - switch status.lowercaseString { + switch status.lowercased() { case "active": return "55561003" case "inactive": return "73425007" case "resolved": return "413322009" @@ -111,9 +132,9 @@ class ViewHelper { return nil } - class func fulfillment_quantity(codes: CDAKCodedEntries, fulfillmentHistory: CDAKFulfillmentHistory, dose: CDAKValueAndUnit) -> String { + class func fulfillment_quantity(_ codes: CDAKCodedEntries, fulfillmentHistory: CDAKFulfillmentHistory, dose: CDAKValueAndUnit) -> String { if codes["RxNorm"]?.count > 0 { - if let qty = fulfillmentHistory.quantity_dispensed.value, dose_value = dose.value { + if let qty = fulfillmentHistory.quantity_dispensed.value, let dose_value = dose.value { let doses = Int(qty / dose_value) return "value=\"\(doses)\"" } @@ -135,18 +156,18 @@ class ViewHelper { //Swift: 1960 12 31 00 00 00 //Ruby: 1960-12-31 00:00:00 -0600 */ - class func value_or_null_flavor(time: Any?) -> String { + class func value_or_null_flavor(_ time: Any?) -> String { if let time = time as? Double { //:number => '%Y%m%d%H%M%S' //return "value='#{Time.at(time).utc.to_formatted_s(:number)}'" - let d = NSDate(timeIntervalSince1970: NSTimeInterval(time)) + let d = Date(timeIntervalSince1970: TimeInterval(time)) return "value=\"\(d.stringFormattedAsHDSDateNumber)\"" } else { return "nullFlavor='UNK'" } } - class func dose_quantity(codes: CDAKCodedEntries, dose: [String:String]) -> String { + class func dose_quantity(_ codes: CDAKCodedEntries, dose: [String:String]) -> String { if codes["RxNorm"]?.count > 0 { return "value = '1'" } else { @@ -157,30 +178,30 @@ class ViewHelper { } - class func time_if_not_nil(args: [Int?]?) -> NSDate? { + class func time_if_not_nil(_ args: [Int?]?) -> Date? { if let args = args { - return args.filter({$0 != nil}).map({t in NSDate(timeIntervalSince1970: NSTimeInterval(t!))}).first + return args.filter({$0 != nil}).map({t in Date(timeIntervalSince1970: TimeInterval(t!))}).first } else { return nil } } - class func time_if_not_nil(args: Int?...) -> NSDate? { - return args.filter({$0 != nil}).map({t in NSDate(timeIntervalSince1970: NSTimeInterval(t!))}).first + class func time_if_not_nil(_ args: Int?...) -> Date? { + return args.filter({$0 != nil}).map({t in Date(timeIntervalSince1970: TimeInterval(t!))}).first } - class func is_num(str: String?) -> Bool { - if let str = str, _ = Double(str) { + class func is_num(_ str: String?) -> Bool { + if let str = str, let _ = Double(str) { return true } return false } - class func is_bool(str: String?) -> Bool { - return ["true","false"].contains(str != nil ? str!.lowercaseString : "") + class func is_bool(_ str: String?) -> Bool { + return ["true","false"].contains(str != nil ? str!.lowercased() : "") } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/import/bulk_record_importer.swift b/CDAKit/health-data-standards/lib/import/bulk_record_importer.swift index a62b3d0..e67969f 100644 --- a/CDAKit/health-data-standards/lib/import/bulk_record_importer.swift +++ b/CDAKit/health-data-standards/lib/import/bulk_record_importer.swift @@ -9,23 +9,23 @@ import Foundation import Fuzi -public enum CDAKImportError : ErrorType { - case NotImplemented - case UnableToDetermineFormat - case NoClinicalDocumentElement - case InvalidXML +public enum CDAKImportError : Error { + case notImplemented + case unableToDetermineFormat + case noClinicalDocumentElement + case invalidXML } internal class CDAKImport_BulkRecordImporter { - internal class func importRecord(XMLString: String, providier_map:[String:CDAKProvider] = [:]) throws -> CDAKRecord { + internal class func importRecord(_ XMLString: String, providier_map:[String:CDAKProvider] = [:]) throws -> CDAKRecord { do { - let doc = try XMLDocument(string: XMLString, encoding: NSUTF8StringEncoding) + let doc = try XMLDocument(string: XMLString, encoding: String.Encoding.utf8) if let root = doc.root { - if let root_element_name = root.tag where root_element_name == "ClinicalDocument" { + if let root_element_name = root.tag , root_element_name == "ClinicalDocument" { doc.definePrefix("cda", defaultNamespace: "urn:hl7-org:v3") doc.definePrefix("sdtc", defaultNamespace: "urn:hl7-org:sdtc") @@ -45,7 +45,7 @@ internal class CDAKImport_BulkRecordImporter { return record } else if doc.xpath("/cda:ClinicalDocument/cda:templateId[@root='2.16.840.1.113883.10.20.24.1.2']").count > 0 { print("QRDA1 not (yet) supported") - throw CDAKImportError.NotImplemented + throw CDAKImportError.notImplemented } else if doc.xpath("/cda:ClinicalDocument/cda:templateId[@root='2.16.840.1.113883.10.20.22.1.1']").count > 0 && CDAKGlobals.sharedInstance.attemptNonStandardCDAImport == true { //last ditch "we have a general US header, but that's about it" print("Deteremined XML document format as: Non-Standard CDA. This may or may not import completely.") @@ -55,24 +55,24 @@ internal class CDAKImport_BulkRecordImporter { return record } else { print("Unable to determinate document template/type of CDA document") - throw CDAKImportError.UnableToDetermineFormat + throw CDAKImportError.unableToDetermineFormat } } else { print("XML does not appear to be a valid ClinicalDocument") - throw CDAKImportError.NoClinicalDocumentElement + throw CDAKImportError.noClinicalDocumentElement } } else { - throw CDAKImportError.InvalidXML + throw CDAKImportError.invalidXML } } catch let error as XMLError { switch error { - case .ParserFailure, .InvalidData: print(error) - case .LibXMLError(let code, let message): + case .parserFailure, .invalidData: print(error) + case .libXMLError(let code, let message): print("libxml error code: \(code), message: \(message)") default: print(error) } - throw CDAKImportError.InvalidXML + throw CDAKImportError.invalidXML } } diff --git a/CDAKit/health-data-standards/lib/import/c32/c32_care_goal_importer.swift b/CDAKit/health-data-standards/lib/import/c32/c32_care_goal_importer.swift index f890b93..253794b 100644 --- a/CDAKit/health-data-standards/lib/import/c32/c32_care_goal_importer.swift +++ b/CDAKit/health-data-standards/lib/import/c32/c32_care_goal_importer.swift @@ -17,7 +17,7 @@ class CDAKImport_C32_CareGoalImporter: CDAKImport_CDA_SectionImporter { } // NOTE this returns a generic "CDAKEntry" - but it could be any number of sub-types - override func create_entry(goal_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKEntry? { + override func create_entry(_ goal_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKEntry? { //original Ruby used "name" - which is "node_name" //looks like Fuzi calls this "tag" @@ -41,4 +41,4 @@ class CDAKImport_C32_CareGoalImporter: CDAKImport_CDA_SectionImporter { return nil } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/import/c32/c32_condition_importer.swift b/CDAKit/health-data-standards/lib/import/c32/c32_condition_importer.swift index 4e92f67..f2c49f7 100644 --- a/CDAKit/health-data-standards/lib/import/c32/c32_condition_importer.swift +++ b/CDAKit/health-data-standards/lib/import/c32/c32_condition_importer.swift @@ -26,7 +26,7 @@ class CDAKImport_C32_ConditionImporter: CDAKImport_CDA_ConditionImporter { entry_class = CDAKCondition.self } - override func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKCondition? { + override func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKCondition? { if let condition = super.create_entry(entry_element, nrh: nrh) { extract_cause_of_death(entry_element, condition: condition) @@ -39,7 +39,7 @@ class CDAKImport_C32_ConditionImporter: CDAKImport_CDA_ConditionImporter { } - private func extract_cause_of_death(entry_element: XMLElement, condition: CDAKCondition) { + fileprivate func extract_cause_of_death(_ entry_element: XMLElement, condition: CDAKCondition) { if let _ = entry_element.xpath(cod_xpath).first { condition.cause_of_death = true @@ -51,8 +51,8 @@ class CDAKImport_C32_ConditionImporter: CDAKImport_CDA_ConditionImporter { } //we should move this out of here. Having these reference codes here seems restrictive. - private func extract_type(entry_element: XMLElement, condition: CDAKCondition) { - if let code_element = entry_element.xpath("./cda:code").first, code = code_element["code"] { + fileprivate func extract_type(_ entry_element: XMLElement, condition: CDAKCondition) { + if let code_element = entry_element.xpath("./cda:code").first, let code = code_element["code"] { switch code { case "404684003": condition.type = "Finding" case "418799008": condition.type = "Symptom" diff --git a/CDAKit/health-data-standards/lib/import/c32/c32_immunization_importer.swift b/CDAKit/health-data-standards/lib/import/c32/c32_immunization_importer.swift index a530f51..349df8f 100644 --- a/CDAKit/health-data-standards/lib/import/c32/c32_immunization_importer.swift +++ b/CDAKit/health-data-standards/lib/import/c32/c32_immunization_importer.swift @@ -21,7 +21,7 @@ class CDAKImport_C32_ImmunizationImporter: CDAKImport_CDA_SectionImporter { } - override func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKImmunization? { + override func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKImmunization? { if let immunization = super.create_entry(entry_element, nrh: nrh) as? CDAKImmunization { extract_negation(entry_element, entry: immunization) @@ -32,7 +32,7 @@ class CDAKImport_C32_ImmunizationImporter: CDAKImport_CDA_SectionImporter { return nil } - private func extract_performer(parent_element: XMLElement, immunization: CDAKImmunization) { + fileprivate func extract_performer(_ parent_element: XMLElement, immunization: CDAKImmunization) { if let performer_element = parent_element.xpath("./cda:performer").first { immunization.performer = import_actor(performer_element) } diff --git a/CDAKit/health-data-standards/lib/import/c32/c32_insurance_provider_importer.swift b/CDAKit/health-data-standards/lib/import/c32/c32_insurance_provider_importer.swift index f59d7a5..3ff162b 100644 --- a/CDAKit/health-data-standards/lib/import/c32/c32_insurance_provider_importer.swift +++ b/CDAKit/health-data-standards/lib/import/c32/c32_insurance_provider_importer.swift @@ -19,7 +19,7 @@ class CDAKImport_C32_InsuranceProviderImporter: CDAKImport_CDA_SectionImporter { } - override func create_entry(payer_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKInsuranceProvider? { + override func create_entry(_ payer_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKInsuranceProvider? { let ip = CDAKInsuranceProvider() if let type = CDAKImport_CDA_SectionImporter.extract_code(payer_element, code_xpath: "./cda:code") { @@ -29,7 +29,7 @@ class CDAKImport_C32_InsuranceProviderImporter: CDAKImport_CDA_SectionImporter { if let payer = payer_element.xpath("./cda:performer/cda:assignedEntity[cda:code[@code='PAYOR']]").first { ip.payer = import_organization(payer) } - ip.guarantors = extract_guarantors(payer_element.xpath("./cda:performer[cda:assignedEntity[cda:code[@code='GUAR']]]")) + ip.guarantors = extract_guarantors(payer_element.xpath("./cda:performer[cda:assignedEntity[cda:code[@code='GUAR']]]") as! XPathNodeSet) if let subscriber = payer_element.xpath("./cda:participant[@typeCode='HLD']/cda:participantRole").first { ip.subscriber = import_person(subscriber) } @@ -53,12 +53,12 @@ class CDAKImport_C32_InsuranceProviderImporter: CDAKImport_CDA_SectionImporter { } - func extract_guarantors(guarantor_elements: XPathNodeSet) -> [CDAKGuarantor] { + func extract_guarantors(_ guarantor_elements: XPathNodeSet) -> [CDAKGuarantor] { var guarantors: [CDAKGuarantor] = [] - for guarantor_element in guarantor_elements { + for guarantor_element in guarantor_elements.enumerated() { let guarantor = CDAKGuarantor() - extract_dates(guarantor_element, entry: guarantor, element_name: "time") - if let guarantor_entity = guarantor_element.xpath("./cda:assignedEntity").first { + extract_dates(guarantor_element.element, entry: guarantor, element_name: "time") + if let guarantor_entity = guarantor_element.element.xpath("./cda:assignedEntity").first { if let person_element = guarantor_entity.xpath("./cda:assignedPerson").first { guarantor.person = import_person(person_element) } @@ -71,4 +71,4 @@ class CDAKImport_C32_InsuranceProviderImporter: CDAKImport_CDA_SectionImporter { return guarantors } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/import/c32/c32_patient_importer.swift b/CDAKit/health-data-standards/lib/import/c32/c32_patient_importer.swift index e0b069a..370240c 100644 --- a/CDAKit/health-data-standards/lib/import/c32/c32_patient_importer.swift +++ b/CDAKit/health-data-standards/lib/import/c32/c32_patient_importer.swift @@ -49,6 +49,8 @@ class CDAKImport_C32_PatientImporter { // Original Ruby: This class is a Singleton. It should be accessed by calling PatientImporter.instance var section_importers: [String:CDAKImport_CDA_SectionImporter] = [:] + var section_importers_keys: [String] = [ "results", "medications", "care_goals", "vital_signs", "allergies", "immunizations", "medical_equipment", + "encounters", "insurance_providers", "procedures", "social_history", "conditions"] init(check_usable: Bool = true) { @@ -72,7 +74,7 @@ class CDAKImport_C32_PatientImporter { /** - parameter check_usable_entries: value for check_usable_entries...importer uses true, stats uses false */ - func check_usable(check_usable_entries: Bool) { + func check_usable(_ check_usable_entries: Bool) { for (_, importer) in section_importers { importer.check_for_usable = check_usable_entries } @@ -86,7 +88,7 @@ class CDAKImport_C32_PatientImporter { will have the "cda" namespace registered to "urn:hl7-org:v3" - returns: a Mongoid model representing the patient */ - func parse_c32(doc: XMLDocument) -> CDAKRecord { + func parse_c32(_ doc: XMLDocument) -> CDAKRecord { let c32_patient = CDAKRecord() get_demographics(c32_patient, doc: doc) if let patient_role_element = doc.xpath("/cda:ClinicalDocument/cda:recordTarget/cda:patientRole").first { @@ -107,7 +109,7 @@ class CDAKImport_C32_PatientImporter { - parameter c32_patient: to check the conditions on and set the expired property if applicable */ - func check_for_cause_of_death(c32_patient: CDAKRecord) { + func check_for_cause_of_death(_ c32_patient: CDAKRecord) { if let cause_of_death = c32_patient.conditions.filter({$0.cause_of_death == true}).first { c32_patient.expired = true c32_patient.deathdate = cause_of_death.time_of_death @@ -127,14 +129,18 @@ class CDAKImport_C32_PatientImporter { Attention: Changed original Ruby */ - func create_c32_hash(record: CDAKRecord, doc: XMLDocument) { + func create_c32_hash(_ record: CDAKRecord, doc: XMLDocument) { // original Ruby was using "send" - which we can't really do. So I'm not doing that... // I'm going to inspect the section type and then just manually say "oh, you're a Condition" etc. // and set things that way. Not super elegant, but - at least I'll know what's going on let nrh = CDAKImport_CDA_NarrativeReferenceHandler() nrh.build_id_map(doc) - for (section, importer) in section_importers { + + //for (section, importer) in section_importers { + for section in section_importers_keys { + guard let importer = section_importers[section] else { return } + let sections = importer.create_entries(doc, nrh: nrh) switch section { @@ -156,7 +162,7 @@ class CDAKImport_C32_PatientImporter { } } - func get_ids (elem: XMLElement) -> [CDAKCDAIdentifier] { + func get_ids (_ elem: XMLElement) -> [CDAKCDAIdentifier] { return elem.xpath("./cda:id").map({id_entry in CDAKCDAIdentifier(root: id_entry["root"], extension_id: id_entry["extension"])}) } @@ -167,7 +173,7 @@ class CDAKImport_C32_PatientImporter { - parameter patient: A hash that is used to represent the patient - parameter doc: The C32 document parsed by Nokogiri */ - func get_demographics(patient: CDAKRecord, doc: XMLDocument) { + func get_demographics(_ patient: CDAKRecord, doc: XMLDocument) { let effective_date = doc.xpath("/cda:ClinicalDocument/cda:effectiveTime").first?["value"] patient.effective_time = CDAKHL7Helper.timestamp_to_integer(effective_date) @@ -183,7 +189,7 @@ class CDAKImport_C32_PatientImporter { patient.last = patient_element.xpath("cda:name/cda:family").first?.stringValue patient.suffix = patient_element.xpath("cda:name/cda:suffix").first?.stringValue - if let birthdate_in_hl7ts_node = patient_element.xpath("cda:birthTime").first, birthdate_in_hl7ts = birthdate_in_hl7ts_node["value"] { + if let birthdate_in_hl7ts_node = patient_element.xpath("cda:birthTime").first, let birthdate_in_hl7ts = birthdate_in_hl7ts_node["value"] { patient.birthdate = CDAKHL7Helper.timestamp_to_integer(birthdate_in_hl7ts) } @@ -207,10 +213,10 @@ class CDAKImport_C32_PatientImporter { } } - if let marital_status_node = patient_element.xpath("./cda:maritalStatusCode").first, code = marital_status_node["code"] { + if let marital_status_node = patient_element.xpath("./cda:maritalStatusCode").first, let code = marital_status_node["code"] { patient.marital_status = CDAKCodedEntries(codeSystem: "HL7 Marital Status", code: code) } - if let ra_node = patient_element.xpath("./cda:religiousAffiliationCode").first, code = ra_node["code"] { + if let ra_node = patient_element.xpath("./cda:religiousAffiliationCode").first, let code = ra_node["code"] { patient.religious_affiliation = CDAKCodedEntries(codeSystem: "Religious Affiliation", code: code) } diff --git a/CDAKit/health-data-standards/lib/import/cat1/cat1_header.swift b/CDAKit/health-data-standards/lib/import/cat1/cat1_header.swift index 651a61b..ff548af 100644 --- a/CDAKit/health-data-standards/lib/import/cat1/cat1_header.swift +++ b/CDAKit/health-data-standards/lib/import/cat1/cat1_header.swift @@ -17,13 +17,13 @@ import Fuzi class CDAKImport_cat1_HeaderImporter { - class func import_header(doc: XMLDocument) -> CDAKQRDAHeader { + class func import_header(_ doc: XMLDocument) -> CDAKQRDAHeader { let header = CDAKQRDAHeader() set_header(header, doc: doc) return header } - class func set_header(header: CDAKQRDAHeader, doc: XMLDocument) { + class func set_header(_ header: CDAKQRDAHeader, doc: XMLDocument) { set_confidentiality_code(header, doc: doc) //done set_creation_date(header, doc: doc) //done set_custodian(header, doc: doc) //done @@ -37,30 +37,30 @@ class CDAKImport_cat1_HeaderImporter { } - class func set_creation_date(header: CDAKQRDAHeader, doc: XMLDocument) { + class func set_creation_date(_ header: CDAKQRDAHeader, doc: XMLDocument) { let effective_date = doc.xpath("/cda:ClinicalDocument/cda:effectiveTime").first?["value"] if let a_time = CDAKHL7Helper.timestamp_to_integer(effective_date) { - header.time = NSDate(timeIntervalSince1970: a_time) + header.time = Date(timeIntervalSince1970: a_time) } } - class func set_confidentiality_code(header: CDAKQRDAHeader, doc: XMLDocument) { + class func set_confidentiality_code(_ header: CDAKQRDAHeader, doc: XMLDocument) { let confidentialityCode = doc.xpath("/cda:ClinicalDocument/cda:confidentialityCode").first?["code"] - if let confidentialityCode = confidentialityCode, confidentiality = CDAKConfidentialityCodes(rawValue: confidentialityCode) { + if let confidentialityCode = confidentialityCode, let confidentiality = CDAKConfidentialityCodes(rawValue: confidentialityCode) { header.confidentiality = confidentiality } } - class func set_authors(header: CDAKQRDAHeader, doc: XMLDocument) { + class func set_authors(_ header: CDAKQRDAHeader, doc: XMLDocument) { header.authors = doc.xpath("./cda:author").map({author in get_authors(author)}) } - class func set_title(header: CDAKQRDAHeader, doc: XMLDocument) { + class func set_title(_ header: CDAKQRDAHeader, doc: XMLDocument) { header.title = doc.xpath("/cda:ClinicalDocument/cda:title").first?.stringValue } - class func get_authors(elem: XMLElement) -> CDAKQRDAAuthor { + class func get_authors(_ elem: XMLElement) -> CDAKQRDAAuthor { let author = CDAKQRDAAuthor() if let time = get_time(elem) { @@ -73,7 +73,7 @@ class CDAKImport_cat1_HeaderImporter { author.telecoms = assignedAuthor.xpath("./cda:telecom").flatMap({tele in CDAKImport_CDA_LocatableImportUtils.import_telecom(tele)}) if let person_info = assignedAuthor.xpath("./cda:assignedPerson/cda:name").first { - author.person = CDAKPerson(given_name: person_info.xpath("./cda:given").first?.stringValue, family_name: person_info.xpath("./cda:family").first?.stringValue, prefix: person_info.xpath("./cda:prefix").first?.stringValue, suffix: person_info.xpath("./cda:suffix").first?.stringValue) + author.person = CDAKPerson(prefix: person_info.xpath("./cda:prefix").first?.stringValue, given_name: person_info.xpath("./cda:given").first?.stringValue, family_name: person_info.xpath("./cda:family").first?.stringValue, suffix: person_info.xpath("./cda:suffix").first?.stringValue) } if let device_elem = assignedAuthor.xpath("./assignedAuthoringDevice").first { author.device = get_device(device_elem) @@ -86,14 +86,14 @@ class CDAKImport_cat1_HeaderImporter { return author } - class func get_device(elem: XMLElement) -> CDAKQRDADevice { + class func get_device(_ elem: XMLElement) -> CDAKQRDADevice { let device = CDAKQRDADevice() device.model = elem.xpath("manufacturerModelName").first?.stringValue device.name = elem.xpath("softwareName").first?.stringValue return device } - class func set_custodian(header: CDAKQRDAHeader, doc: XMLDocument) { + class func set_custodian(_ header: CDAKQRDAHeader, doc: XMLDocument) { if let custodian_elem = doc.xpath("/cda:ClinicalDocument/cda:custodian/cda:assignedCustodian").first { let aCustodian = CDAKQRDACustodian() @@ -111,11 +111,11 @@ class CDAKImport_cat1_HeaderImporter { } - class func import_ids (elem: XMLElement) -> [CDAKCDAIdentifier] { + class func import_ids (_ elem: XMLElement) -> [CDAKCDAIdentifier] { return elem.xpath("./cda:id").map({id_entry in CDAKCDAIdentifier(root: id_entry["root"], extension_id: id_entry["extension"])}) } - class func set_legal_authenticator(header: CDAKQRDAHeader, doc: XMLDocument) { + class func set_legal_authenticator(_ header: CDAKQRDAHeader, doc: XMLDocument) { if let auth_info = doc.xpath("/cda:ClinicalDocument/cda:legalAuthenticator").first { let legal = CDAKQRDALegalAuthenticator() if let time = get_time(auth_info) { @@ -127,7 +127,7 @@ class CDAKImport_cat1_HeaderImporter { legal.addresses = assignedEntity.xpath("./cda:addr").flatMap({addr in CDAKImport_CDA_LocatableImportUtils.import_address(addr)}) legal.telecoms = assignedEntity.xpath("./cda:telecom").flatMap({tele in CDAKImport_CDA_LocatableImportUtils.import_telecom(tele)}) if let name_info = assignedEntity.xpath("./cda:assignedPerson/cda:name").first { - legal.person = CDAKPerson(given_name: name_info.xpath("./cda:given").first?.stringValue, family_name: name_info.xpath("./cda:family").first?.stringValue, prefix: name_info.xpath("./cda:suffix").first?.stringValue, suffix: name_info.xpath("./cda:suffix").first?.stringValue) + legal.person = CDAKPerson(prefix: name_info.xpath("./cda:suffix").first?.stringValue, given_name: name_info.xpath("./cda:given").first?.stringValue, family_name: name_info.xpath("./cda:family").first?.stringValue, suffix: name_info.xpath("./cda:suffix").first?.stringValue) } } if let org_info = auth_info.xpath("./cda:representedOrganization").first { @@ -139,18 +139,18 @@ class CDAKImport_cat1_HeaderImporter { } } - class func get_time(elem: XMLElement) -> NSDate? { + class func get_time(_ elem: XMLElement) -> Date? { if let time_info = elem.xpath("./cda:time").first?["value"] { //20130418090000+0500 ... ewwwwwwwww //https://github.com/chb/sample_ccdas/blob/master/EMERGE/Patient-673.xml#L226 if let a_time = CDAKHL7Helper.timestamp_to_integer(time_info) { - return NSDate(timeIntervalSince1970: a_time) + return Date(timeIntervalSince1970: a_time) } } return nil } - class func import_organization(organization_element: XMLElement) -> CDAKOrganization? { + class func import_organization(_ organization_element: XMLElement) -> CDAKOrganization? { if let org = CDAKImport_CDA_OrganizationImporter.extract_organization(organization_element) { let cdaOrg = CDAKOrganization() cdaOrg.addresses = org.addresses @@ -163,7 +163,7 @@ class CDAKImport_cat1_HeaderImporter { } - class func set_person(header: CDAKQRDAHeader, doc: XMLDocument) { + class func set_person(_ header: CDAKQRDAHeader, doc: XMLDocument) { } } diff --git a/CDAKit/health-data-standards/lib/import/ccda/ccda_patient_importer.swift b/CDAKit/health-data-standards/lib/import/ccda/ccda_patient_importer.swift index 6fcd780..7d87a58 100644 --- a/CDAKit/health-data-standards/lib/import/ccda/ccda_patient_importer.swift +++ b/CDAKit/health-data-standards/lib/import/ccda/ccda_patient_importer.swift @@ -32,8 +32,8 @@ class CDAKImport_CCDA_PatientImporter: CDAKImport_C32_PatientImporter { } - func parse_ccda(doc: XMLDocument) -> CDAKRecord { + func parse_ccda(_ doc: XMLDocument) -> CDAKRecord { return parse_c32(doc) } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_allergy_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_allergy_importer.swift index 4660012..8b5f6b5 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_allergy_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_allergy_importer.swift @@ -30,7 +30,7 @@ class CDAKImport_CDA_AllergyImporter: CDAKImport_CDA_SectionImporter { check_for_usable = false } - override func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKAllergy? { + override func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKAllergy? { if let allergy = super.create_entry(entry_element, nrh: nrh) as? CDAKAllergy { diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_condition_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_condition_importer.swift index af047f7..d5c5418 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_condition_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_condition_importer.swift @@ -30,7 +30,7 @@ class CDAKImport_CDA_ConditionImporter: CDAKImport_CDA_SectionImporter { } - override func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKCondition? { + override func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKCondition? { if let condition = super.create_entry(entry_element, nrh: nrh) as? CDAKCondition { @@ -49,14 +49,14 @@ class CDAKImport_CDA_ConditionImporter: CDAKImport_CDA_SectionImporter { } - private func extract_ordinality(parent_element: XMLElement, condition: CDAKCondition) { + fileprivate func extract_ordinality(_ parent_element: XMLElement, condition: CDAKCondition) { if let ordinality_element = parent_element.xpath(ordinality_xpath).first { condition.ordinality.addCodes(CDAKImport_CDA_SectionImporter.extract_code(ordinality_element, code_xpath: ".")) } } - private func extract_priority(parent_element: XMLElement, condition: CDAKCondition) { - if let priority_xpath = priority_xpath, priority_element = parent_element.xpath(priority_xpath).first, priority_value = priority_element["value"], priority_int = Int(priority_value) { + fileprivate func extract_priority(_ parent_element: XMLElement, condition: CDAKCondition) { + if let priority_xpath = priority_xpath, let priority_element = parent_element.xpath(priority_xpath).first, let priority_value = priority_element["value"], let priority_int = Int(priority_value) { condition.priority = priority_int } } diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_encounter_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_encounter_importer.swift index a2d14ba..7f0ddc2 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_encounter_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_encounter_importer.swift @@ -22,7 +22,7 @@ class CDAKImport_CDA_EncounterImporter: CDAKImport_CDA_SectionImporter { //# TODO Extract Discharge Disposition - override func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKEncounter? { + override func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKEncounter? { if let encounter = super.create_entry(entry_element, nrh: nrh) as? CDAKEncounter { @@ -46,13 +46,13 @@ class CDAKImport_CDA_EncounterImporter: CDAKImport_CDA_SectionImporter { } - private func extract_performer(parent_element: XMLElement, encounter: CDAKEncounter) { + fileprivate func extract_performer(_ parent_element: XMLElement, encounter: CDAKEncounter) { if let performer_element = parent_element.xpath("./cda:performer").first { encounter.performer = import_actor(performer_element) } } - private func extract_facility(parent_element: XMLElement, encounter: CDAKEncounter) { + fileprivate func extract_facility(_ parent_element: XMLElement, encounter: CDAKEncounter) { if let participant_element = parent_element.xpath("./cda:participant[@typeCode='LOC']/cda:participantRole[@classCode='SDLOC']").first { let facility = CDAKFacility() @@ -69,7 +69,7 @@ class CDAKImport_CDA_EncounterImporter: CDAKImport_CDA_SectionImporter { } } - private func extract_reason(parent_element: XMLElement, encounter: CDAKEncounter, nrh: CDAKImport_CDA_NarrativeReferenceHandler) { + fileprivate func extract_reason(_ parent_element: XMLElement, encounter: CDAKEncounter, nrh: CDAKImport_CDA_NarrativeReferenceHandler) { if let reason_element = parent_element.xpath(reason_xpath).first { let reason = CDAKReason() //NOTE: was originally CDAKEntry - we made it a "CDAKReason" since it was a dedicated type extract_codes(reason_element, entry: reason) @@ -80,21 +80,21 @@ class CDAKImport_CDA_EncounterImporter: CDAKImport_CDA_SectionImporter { } } - private func extract_admission(parent_element: XMLElement, encounter: CDAKEncounter) { + fileprivate func extract_admission(_ parent_element: XMLElement, encounter: CDAKEncounter) { encounter.admit_type.addCodes(CDAKImport_CDA_SectionImporter.extract_code(parent_element, code_xpath: "./cda:priorityCode")) } - private func extract_discharge_disposition(parent_element: XMLElement, encounter: CDAKEncounter) { + fileprivate func extract_discharge_disposition(_ parent_element: XMLElement, encounter: CDAKEncounter) { encounter.discharge_time = encounter.end_time encounter.discharge_disposition.addCodes(CDAKImport_CDA_SectionImporter.extract_code(parent_element, code_xpath: "./sdtc:dischargeDispositionCode")) } - private func extract_transfers(parent_element: XMLElement, encounter: CDAKEncounter) { + fileprivate func extract_transfers(_ parent_element: XMLElement, encounter: CDAKEncounter) { if let transfer_from_element = parent_element.xpath("./cda:participant[@typeCode='ORG']").first { let transfer_from = CDAKTransfer() - if let a_time = transfer_from_element.xpath("./cda:time").first, time_value = a_time["value"] { + if let a_time = transfer_from_element.xpath("./cda:time").first, let time_value = a_time["value"] { transfer_from.time = Double(time_value) } if let transfer_from_subelement = transfer_from_element.xpath("./cda:participantRole[@classCode='LOCE']").first { @@ -105,7 +105,7 @@ class CDAKImport_CDA_EncounterImporter: CDAKImport_CDA_SectionImporter { if let transfer_to_element = parent_element.xpath("./cda:participant[@typeCode='DST']").first { let transfer_to = CDAKTransfer() - if let a_time = transfer_to_element.xpath("./cda:time").first, time_value = a_time["value"] { + if let a_time = transfer_to_element.xpath("./cda:time").first, let time_value = a_time["value"] { transfer_to.time = Double(time_value) } if let transfer_from_subelement = transfer_to_element.xpath("./cda:participantRole[@classCode='LOCE']").first { diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_entry_finder.swift b/CDAKit/health-data-standards/lib/import/cda/cda_entry_finder.swift index 7d3f9a0..2555c3a 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_entry_finder.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_entry_finder.swift @@ -16,9 +16,9 @@ class CDAKImport_CDA_EntryFinder { self.entry_xpath = entry_xpath } - func entries(doc: XMLDocument) -> XPathNodeSet { + func entries(_ doc: XMLDocument) -> XPathNodeSet { let entry_elements = doc.xpath(entry_xpath) - return entry_elements + return entry_elements as! XPathNodeSet //Should probably review this. // I think we can get away with just returning the node set // since the closure will execute outside of this context diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_locatable_import_utils.swift b/CDAKit/health-data-standards/lib/import/cda/cda_locatable_import_utils.swift index 2401c0c..e2c5426 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_locatable_import_utils.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_locatable_import_utils.swift @@ -13,7 +13,7 @@ import Fuzi //# Helpers for importing C32 addresses and telecoms class CDAKImport_CDA_LocatableImportUtils { - class func import_address(address_element: XMLElement) -> CDAKAddress? { + class func import_address(_ address_element: XMLElement) -> CDAKAddress? { let address = CDAKAddress() address.use = address_element["use"] address.street = address_element.xpath("./cda:streetAddressLine").map({$0.stringValue}) @@ -28,7 +28,7 @@ class CDAKImport_CDA_LocatableImportUtils { return address } - class func import_telecom(telecom_element: XMLElement) -> CDAKTelecom? { + class func import_telecom(_ telecom_element: XMLElement) -> CDAKTelecom? { let tele = CDAKTelecom() tele.value = telecom_element["value"] tele.use = telecom_element["use"] diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_medical_equipment_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_medical_equipment_importer.swift index c23d9ac..318c013 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_medical_equipment_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_medical_equipment_importer.swift @@ -20,7 +20,7 @@ class CDAKImport_CDA_MedicalEquipmentImporter: CDAKImport_CDA_SectionImporter { } - override func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKMedicalEquipment? { + override func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKMedicalEquipment? { if let medical_equipment = super.create_entry(entry_element, nrh: nrh) as? CDAKMedicalEquipment { @@ -35,19 +35,19 @@ class CDAKImport_CDA_MedicalEquipmentImporter: CDAKImport_CDA_SectionImporter { } - private func extract_manufacturer(entry_element: XMLElement, entry: CDAKMedicalEquipment) { + fileprivate func extract_manufacturer(_ entry_element: XMLElement, entry: CDAKMedicalEquipment) { if let manufacturer = entry_element.xpath("./cda:participant/cda:participantRole/cda:scopingEntity/cda:desc").first?.stringValue { - entry.manufacturer = manufacturer.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) + entry.manufacturer = manufacturer.trimmingCharacters(in: .whitespaces) } } - private func extract_removal_time(entry_element: XMLElement, entry: CDAKMedicalEquipment) { - if let removal_time_entry = entry_element.xpath("cda:effectiveTime/cda:high").first, removal_time_value = removal_time_entry["value"] { + fileprivate func extract_removal_time(_ entry_element: XMLElement, entry: CDAKMedicalEquipment) { + if let removal_time_entry = entry_element.xpath("cda:effectiveTime/cda:high").first, let removal_time_value = removal_time_entry["value"] { entry.removal_time = CDAKHL7Helper.timestamp_to_integer(removal_time_value) } } - private func extract_anatomical_structure(entry_element: XMLElement, entry: CDAKMedicalEquipment) { + fileprivate func extract_anatomical_structure(_ entry_element: XMLElement, entry: CDAKMedicalEquipment) { if let site = entry_element.xpath(anatomical_xpath).first { entry.anatomical_structure.addCodes(CDAKImport_CDA_SectionImporter.extract_code(site, code_xpath: ".")) } diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_medication_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_medication_importer.swift index 4d90e58..1366a7c 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_medication_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_medication_importer.swift @@ -40,7 +40,7 @@ class CDAKImport_CDA_MedicationImporter: CDAKImport_CDA_SectionImporter { entry_class = CDAKMedication.self } - override func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKMedication? { + override func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKMedication? { if let medication = super.create_entry(entry_element, nrh: nrh) as? CDAKMedication { @@ -99,7 +99,7 @@ class CDAKImport_CDA_MedicationImporter: CDAKImport_CDA_SectionImporter { } - private func extract_fulfillment_history(parent_element: XMLElement, medication: CDAKMedication) { + fileprivate func extract_fulfillment_history(_ parent_element: XMLElement, medication: CDAKMedication) { let fhs = parent_element.xpath("./cda:entryRelationship/cda:supply[@moodCode='EVN']") for fh_element in fhs { let fulfillment_history = CDAKFulfillmentHistory() @@ -113,7 +113,7 @@ class CDAKImport_CDA_MedicationImporter: CDAKImport_CDA_SectionImporter { if let quantity_dispensed = extract_scalar(fh_element, scalar_xpath: "./cda:quantity") { fulfillment_history.quantity_dispensed = quantity_dispensed } - if let fill_number = fh_element.xpath(fill_number_xpath).first?.stringValue, fill_number_int = Int(fill_number) { + if let fill_number = fh_element.xpath(fill_number_xpath).first?.stringValue, let fill_number_int = Int(fill_number) { fulfillment_history.fill_number = fill_number_int } medication.fulfillment_history.append(fulfillment_history) @@ -121,7 +121,7 @@ class CDAKImport_CDA_MedicationImporter: CDAKImport_CDA_SectionImporter { } - private func extract_order_information(parent_element: XMLElement, medication: CDAKMedication) { + fileprivate func extract_order_information(_ parent_element: XMLElement, medication: CDAKMedication) { let order_elements = parent_element.xpath("./cda:entryRelationship[@typeCode='REFR']/cda:supply[@moodCode='INT']") for order_element in order_elements { let order_information = CDAKOrderInformation() @@ -131,7 +131,7 @@ class CDAKImport_CDA_MedicationImporter: CDAKImport_CDA_SectionImporter { } order_information.order_number = order_element.xpath("./cda:id").first?["root"] - if let fills = order_element.xpath("./cda:repeatNumber").first?["value"], fills_int = Int(fills) { + if let fills = order_element.xpath("./cda:repeatNumber").first?["value"], let fills_int = Int(fills) { order_information.fills = fills_int } if let quantity_ordered = extract_scalar(order_element, scalar_xpath: "./cda:quantity") { @@ -141,10 +141,10 @@ class CDAKImport_CDA_MedicationImporter: CDAKImport_CDA_SectionImporter { } } - private func extract_administration_timing(parent_element: XMLElement, medication: CDAKMedication) { + fileprivate func extract_administration_timing(_ parent_element: XMLElement, medication: CDAKMedication) { if let administration_timing_element = parent_element.xpath("./cda:effectiveTime[2]").first { if let institutionSpecified = administration_timing_element["institutionSpecified"] { - let inst = institutionSpecified.lowercaseString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) + let inst = institutionSpecified.lowercased().trimmingCharacters(in: .whitespaces) switch inst { case "true": medication.administration_timing.institution_specified = true case "false": medication.administration_timing.institution_specified = false @@ -157,7 +157,7 @@ class CDAKImport_CDA_MedicationImporter: CDAKImport_CDA_SectionImporter { } } - private func extract_dose_restriction(parent_element: XMLElement, medication: CDAKMedication) { + fileprivate func extract_dose_restriction(_ parent_element: XMLElement, medication: CDAKMedication) { if let dre = parent_element.xpath("./cda:maxDoseQuantity").first { if let numerator = extract_scalar(dre, scalar_xpath: "./cda:numerator") { medication.dose_restriction.numerator = numerator @@ -169,4 +169,4 @@ class CDAKImport_CDA_MedicationImporter: CDAKImport_CDA_SectionImporter { } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_narrative_reference_handler.swift b/CDAKit/health-data-standards/lib/import/cda/cda_narrative_reference_handler.swift index 88a0b72..de82291 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_narrative_reference_handler.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_narrative_reference_handler.swift @@ -12,7 +12,7 @@ import Fuzi class CDAKImport_CDA_NarrativeReferenceHandler { var id_map: [String:String] = [:] // this might be an XMLElement - not clear yet - func build_id_map(doc: XMLDocument) { + func build_id_map(_ doc: XMLDocument) { let path = "//*[@ID]" let ids = doc.xpath(path) for id in ids { @@ -27,7 +27,8 @@ class CDAKImport_CDA_NarrativeReferenceHandler { - parameter tag: the XML tag you're looking for - returns: text description of the tag */ - func lookup_tag(var tag: String) -> String? { + func lookup_tag(_ tag: String) -> String? { + var tag = tag var value = id_map[tag] //# Not sure why, but sometimes the reference is # and the ID value is , and //# sometimes it is #. We look for both. diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_organization_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_organization_importer.swift index 15bc85e..a5f8f1f 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_organization_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_organization_importer.swift @@ -11,7 +11,7 @@ import Fuzi class CDAKImport_CDA_OrganizationImporter { - class func extract_organization(org_element: XMLElement?) -> CDAKOrganization? { + class func extract_organization(_ org_element: XMLElement?) -> CDAKOrganization? { guard let org_element = org_element else { return nil } diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_procedure_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_procedure_importer.swift index e88c1c7..8bc839e 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_procedure_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_procedure_importer.swift @@ -18,7 +18,7 @@ class CDAKImport_CDA_ProcedureImporter: CDAKImport_CDA_SectionImporter { entry_class = CDAKProcedure.self } - override func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKEntry? { + override func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKEntry? { if let procedure = super.create_entry(entry_element, nrh: nrh) as? CDAKProcedure { @@ -36,24 +36,24 @@ class CDAKImport_CDA_ProcedureImporter: CDAKImport_CDA_SectionImporter { } - private func extract_ordinality(parent_element: XMLElement, procedure: CDAKProcedure) { + fileprivate func extract_ordinality(_ parent_element: XMLElement, procedure: CDAKProcedure) { if let ordinality_element = parent_element.xpath(ordinality_xpath).first { procedure.ordinality.addCodes(CDAKImport_CDA_SectionImporter.extract_code(ordinality_element, code_xpath: ".")) } } - private func extract_performer(parent_element: XMLElement, procedure: CDAKProcedure) { + fileprivate func extract_performer(_ parent_element: XMLElement, procedure: CDAKProcedure) { if let performer_element = parent_element.xpath("./cda:performer").first { procedure.performer = import_actor(performer_element) } } - private func extract_anatomical_target(parent_element: XMLElement, procedure: CDAKProcedure) { + fileprivate func extract_anatomical_target(_ parent_element: XMLElement, procedure: CDAKProcedure) { procedure.anatomical_target.addCodes(CDAKImport_CDA_SectionImporter.extract_code(parent_element, code_xpath: "./cda:targetSiteCode")) } - private func extract_scalar(parent_element: XMLElement, procedure: CDAKProcedure) { - if let scalar_element = parent_element.xpath("./cda:value").first, scalar_type = scalar_element["xsi:type"] { + fileprivate func extract_scalar(_ parent_element: XMLElement, procedure: CDAKProcedure) { + if let scalar_element = parent_element.xpath("./cda:value").first, let scalar_type = scalar_element["xsi:type"] { switch scalar_type { case "PQ": procedure.set_value(scalar_element["value"], units: scalar_element["unit"]) @@ -67,4 +67,4 @@ class CDAKImport_CDA_ProcedureImporter: CDAKImport_CDA_SectionImporter { } } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_provider_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_provider_importer.swift index bf922bc..e23ad47 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_provider_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_provider_importer.swift @@ -18,7 +18,7 @@ class CDAKImport_CDA_ProviderImporter { - parameter doc: It is expected that the root node of this document will have the "cda" namespace registered to "urn:hl7-org:v3" - returns: an array of providers found in the document */ - class func extract_providers(doc: XMLDocument, patient:CDAKPerson? = nil) -> [CDAKProviderPerformance] { + class func extract_providers(_ doc: XMLDocument, patient:CDAKPerson? = nil) -> [CDAKProviderPerformance] { let performers = doc.xpath("//cda:documentationOf/cda:serviceEvent/cda:performer") @@ -47,7 +47,7 @@ class CDAKImport_CDA_ProviderImporter { return performances } - class func extract_provider_data(performer:XMLElement, use_dates:Bool = true, entity_path: String = "./cda:assignedEntity") -> [String:Any] { + class func extract_provider_data(_ performer:XMLElement, use_dates:Bool = true, entity_path: String = "./cda:assignedEntity") -> [String:Any] { var provider_data: [String:Any] = [:] @@ -115,9 +115,9 @@ class CDAKImport_CDA_ProviderImporter { } - class func extract_date(subject: XMLElement, query: String) -> Double? { + class func extract_date(_ subject: XMLElement, query: String) -> Double? { if let date = extract_data(subject, query: query) { - return NSDate.dateFromHDSFormattedString(date)?.timeIntervalSince1970 + return Date.dateFromHDSFormattedString(date)?.timeIntervalSince1970 } return nil } @@ -125,9 +125,9 @@ class CDAKImport_CDA_ProviderImporter { /** - returns: nil if result is an empty string, block allows text munging of result if there is one */ - class func extract_data(subject: XMLElement, query: String) -> String? { + class func extract_data(_ subject: XMLElement, query: String) -> String? { let result = subject.xpath(query).first?.stringValue - if let result = result where result != "" { + if let result = result , result != "" { return result } return nil diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_result_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_result_importer.swift index 1dc7633..885e0ee 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_result_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_result_importer.swift @@ -17,7 +17,7 @@ class CDAKImport_CDA_ResultImporter: CDAKImport_CDA_SectionImporter { entry_class = CDAKLabResult.self } - override func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKLabResult? { + override func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKLabResult? { if let result = super.create_entry(entry_element, nrh: nrh) as? CDAKLabResult { @@ -32,17 +32,17 @@ class CDAKImport_CDA_ResultImporter: CDAKImport_CDA_SectionImporter { } - private func extract_interpretation(parent_element: XMLElement, result: CDAKLabResult) { + fileprivate func extract_interpretation(_ parent_element: XMLElement, result: CDAKLabResult) { if let interpretation_element = parent_element.xpath("./cda:interpretationCode").first { result.interpretation.addCodes(CDAKImport_CDA_SectionImporter.extract_code(interpretation_element, code_xpath: ".")) } } - private func extract_reference_range(parent_element: XMLElement, result: CDAKLabResult) { + fileprivate func extract_reference_range(_ parent_element: XMLElement, result: CDAKLabResult) { if let reference_range = parent_element.xpath("./cda:referenceRange/cda:observationRange/cda:text").first?.stringValue { result.reference_range = reference_range } } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_section_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_section_importer.swift index 1f367de..d0099b6 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_section_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_section_importer.swift @@ -44,13 +44,13 @@ class CDAKImport_CDA_SectionImporter { - parameter doc: It is expected that the root node of this document will have the "cda" namespace registered to "urn:hl7-org:v3" measure definition - returns: will be a list of CDAKEntry objects */ - func create_entries(doc: XMLDocument, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> [CDAKEntry] { + func create_entries(_ doc: XMLDocument, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> [CDAKEntry] { var entry_list: [CDAKEntry] = [] let entry_elements = entry_finder.entries(doc) - - for entry_element in entry_elements { - if let entry = create_entry(entry_element, nrh: nrh) { + + for entry_element in entry_elements.enumerated() { + if let entry = create_entry(entry_element.element, nrh: nrh) { if check_for_usable == true { if entry.usable() { entry_list.append(entry) @@ -65,7 +65,7 @@ class CDAKImport_CDA_SectionImporter { } - func create_entry(entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKEntry? { + func create_entry(_ entry_element: XMLElement, nrh: CDAKImport_CDA_NarrativeReferenceHandler = CDAKImport_CDA_NarrativeReferenceHandler()) -> CDAKEntry? { let entry = entry_class.init() extract_id(entry_element, entry: entry) @@ -84,7 +84,7 @@ class CDAKImport_CDA_SectionImporter { } - func extract_indication(entry_element: XMLElement, entry: CDAKEntry, indication_xpath: String) -> CDAKEntry? { + func extract_indication(_ entry_element: XMLElement, entry: CDAKEntry, indication_xpath: String) -> CDAKEntry? { if let indication_element = entry_element.xpath(indication_xpath).first { //NOTE: we're not capturing xsi:type="CD" / "CE" etc. // we're goign to flag everything as CE ("Coded with Equivalents") @@ -100,25 +100,25 @@ class CDAKImport_CDA_SectionImporter { } - func extract_description(parent_element: XMLElement, entry: CDAKEntry, nrh: CDAKImport_CDA_NarrativeReferenceHandler) { + func extract_description(_ parent_element: XMLElement, entry: CDAKEntry, nrh: CDAKImport_CDA_NarrativeReferenceHandler) { let orig_text_ref_element = parent_element.xpath(description_xpath).first let desc_ref_element = parent_element.xpath("./cda:text/cda:reference").first - if let orig_text_ref_element = orig_text_ref_element, val = orig_text_ref_element["value"] { + if let orig_text_ref_element = orig_text_ref_element, let val = orig_text_ref_element["value"] { entry.item_description = nrh.lookup_tag(val) - } else if let desc_ref_element = desc_ref_element, val = desc_ref_element["value"] { + } else if let desc_ref_element = desc_ref_element, let val = desc_ref_element["value"] { entry.item_description = nrh.lookup_tag(val) } else if let elem = parent_element.xpath("./cda:text").first { entry.item_description = elem.stringValue } } - func extract_status(parent_element: XMLElement, entry: CDAKEntry) { - if let status_xpath = status_xpath, status_element = parent_element.xpath(status_xpath).first { + func extract_status(_ parent_element: XMLElement, entry: CDAKEntry) { + if let status_xpath = status_xpath, let status_element = parent_element.xpath(status_xpath).first { entry.status_code.addCodes(CDAKImport_CDA_SectionImporter.extract_code(status_element, code_xpath: ".")) } } - func extract_id(parent_element: XMLElement, entry: CDAKThingWithIdentifier) { + func extract_id(_ parent_element: XMLElement, entry: CDAKThingWithIdentifier) { if let id_element = parent_element.xpath(id_xpath).first { let identifier = CDAKCDAIdentifier() identifier.root = id_element["root"] @@ -127,7 +127,7 @@ class CDAKImport_CDA_SectionImporter { } } - func extract_reason_description(parent_element: XMLElement, entry: CDAKEntry, nrh: CDAKImport_CDA_NarrativeReferenceHandler) { + func extract_reason_description(_ parent_element: XMLElement, entry: CDAKEntry, nrh: CDAKImport_CDA_NarrativeReferenceHandler) { let code_elements = parent_element.xpath(description_xpath) for code_element in code_elements { if let tag = code_element["value"] { @@ -136,7 +136,7 @@ class CDAKImport_CDA_SectionImporter { } } - func extract_codes(parent_element: XMLElement, entry: CDAKThingWithCodes, codes_xpath: String? = nil) { + func extract_codes(_ parent_element: XMLElement, entry: CDAKThingWithCodes, codes_xpath: String? = nil) { let xpath = codes_xpath ?? code_xpath let code_elements = parent_element.xpath(xpath) for code_element in code_elements { @@ -148,11 +148,11 @@ class CDAKImport_CDA_SectionImporter { } } - func add_code_if_present(code_element: XMLElement, entry: CDAKThingWithCodes) { + func add_code_if_present(_ code_element: XMLElement, entry: CDAKThingWithCodes) { entry.codes.addCodes(CDAKImport_CDA_SectionImporter.extract_code(code_element, code_xpath: ".")) } - func extract_dates(parent_element: XMLElement, entry: CDAKThingWithTimes, element_name: String = "effectiveTime") { + func extract_dates(_ parent_element: XMLElement, entry: CDAKThingWithTimes, element_name: String = "effectiveTime") { if let elem = parent_element.xpath("cda:\(element_name)/@value").first { entry.time = CDAKHL7Helper.timestamp_to_integer(elem.stringValue) } @@ -167,7 +167,7 @@ class CDAKImport_CDA_SectionImporter { } } - func extract_values(parent_element: XMLElement, entry: CDAKEntry) { + func extract_values(_ parent_element: XMLElement, entry: CDAKEntry) { if let value_xpath = value_xpath { for elem in parent_element.xpath(value_xpath) { extract_value(parent_element, value_element: elem, entry: entry) @@ -175,12 +175,12 @@ class CDAKImport_CDA_SectionImporter { } } - func extract_value(parent_element: XMLElement, value_element: XMLElement?, entry: CDAKEntry) { + func extract_value(_ parent_element: XMLElement, value_element: XMLElement?, entry: CDAKEntry) { //FIX_ME: - I had to comment some of this out... not the type I was expecting if let value_element = value_element { if let value = value_element["value"] { let unit = value_element["unit"] - entry.set_value(value.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()), units: unit) + entry.set_value(value.trimmingCharacters(in: .whitespaces), units: unit) } else if let _ = value_element["code"] { // there is one example I found where this is being called: // bundle exec rake test TEST=test/unit/import/cat1/tobacco_use_importer_test.rb @@ -194,21 +194,21 @@ class CDAKImport_CDA_SectionImporter { } else { let value = value_element.stringValue let unit = value_element["unit"] - entry.set_value(value.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()), units: unit) + entry.set_value(value.trimmingCharacters(in: .whitespaces), units: unit) } } } - func import_actor(actor_element: XMLElement) -> CDAKProvider { + func import_actor(_ actor_element: XMLElement) -> CDAKProvider { return CDAKImport_ProviderImportUtils.extract_provider(actor_element) } - func import_organization(organization_element: XMLElement) -> CDAKOrganization? { + func import_organization(_ organization_element: XMLElement) -> CDAKOrganization? { return CDAKImport_CDA_OrganizationImporter.extract_organization(organization_element) } - func import_person(person_element: XMLElement?) -> CDAKPerson? { + func import_person(_ person_element: XMLElement?) -> CDAKPerson? { guard let person_element = person_element else { return nil @@ -225,10 +225,10 @@ class CDAKImport_CDA_SectionImporter { return person } - func extract_negation(parent_element: XMLElement, entry: CDAKEntry) { + func extract_negation(_ parent_element: XMLElement, entry: CDAKEntry) { //FIX_ME: does not appear to pull translations if let negation_indicator = parent_element["negationInd"] { - entry.negation_ind = negation_indicator.lowercaseString == "true" + entry.negation_ind = negation_indicator.lowercased() == "true" if entry.negation_ind == true { if let negation_reason_element = parent_element.xpath("./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value | ./cda:entryRelationship[@typeCode='RSON']/cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.27']/cda:code").first { entry.negation_reason.addCodes(CDAKImport_CDA_SectionImporter.extract_code(negation_reason_element, code_xpath: ".")) @@ -244,7 +244,7 @@ class CDAKImport_CDA_SectionImporter { - parameter code_xpath: XPath query to your coded element within the parent. Could even be "." - parameter code_system: optional string to override (or just directly supply) a given code system for this entry. Certain entries (EX: language, race, ethnicity) do not supply a code system directly, but instead rely on an "implied" code system like "CDC Race" which aren't defined in the XML. In this case, the code system tag/name can be supplied directly and then looked up internally (if possible) to obtain the OID, etc. */ - class func extract_code(parent_element: XMLElement, code_xpath: String, code_system: String? = nil) -> CDAKCodedEntry? { + class func extract_code(_ parent_element: XMLElement, code_xpath: String, code_system: String? = nil) -> CDAKCodedEntry? { if let code_element = parent_element.xpath(code_xpath).first { if let code = code_element["code"] { let display_name = code_element["displayName"] @@ -261,7 +261,7 @@ class CDAKImport_CDA_SectionImporter { return nil } - class func extract_codes(parent_element: XMLElement, code_xpath: String) -> CDAKCodedEntries? { + class func extract_codes(_ parent_element: XMLElement, code_xpath: String) -> CDAKCodedEntries? { let code_elements = parent_element.xpath(code_xpath) if code_elements.count > 0 { var codes = CDAKCodedEntries() @@ -278,7 +278,7 @@ class CDAKImport_CDA_SectionImporter { return nil } - func extract_entry_detail(parent_element: XMLElement, xpath: String = ".", codes_xpath: String = "cda:value") -> CDAKEntryDetail? { + func extract_entry_detail(_ parent_element: XMLElement, xpath: String = ".", codes_xpath: String = "cda:value") -> CDAKEntryDetail? { if let element = parent_element.xpath(xpath).first { let detail = CDAKEntryDetail() if let codes = CDAKImport_CDA_SectionImporter.extract_codes(element, code_xpath: codes_xpath) { @@ -292,7 +292,7 @@ class CDAKImport_CDA_SectionImporter { } //Revised - with fixed CDAKValueAndUnit type - func extract_scalar(parent_element: XMLElement, scalar_xpath: String) -> CDAKValueAndUnit? { + func extract_scalar(_ parent_element: XMLElement, scalar_xpath: String) -> CDAKValueAndUnit? { if let scalar_element = parent_element.xpath(scalar_xpath).first { //had to change htis from the original version a bit // we can have doseQuantity, for example, that only has a value and NOT a unit @@ -304,7 +304,7 @@ class CDAKImport_CDA_SectionImporter { if let unit = unit { scalar.unit = unit } - if let value = value, value_as_float = Double(value) { + if let value = value, let value_as_float = Double(value) { scalar.value = value_as_float } return scalar diff --git a/CDAKit/health-data-standards/lib/import/provider_import_utils.swift b/CDAKit/health-data-standards/lib/import/provider_import_utils.swift index 5176512..7f21778 100644 --- a/CDAKit/health-data-standards/lib/import/provider_import_utils.swift +++ b/CDAKit/health-data-standards/lib/import/provider_import_utils.swift @@ -13,22 +13,22 @@ import Fuzi class CDAKImport_ProviderImportUtils { - class func extract_provider(performer: XMLElement, element_name:String = "assignedEntity") -> CDAKProvider { + class func extract_provider(_ performer: XMLElement, element_name:String = "assignedEntity") -> CDAKProvider { let provider_data = CDAKImport_CDA_ProviderImporter.extract_provider_data(performer, use_dates: false, entity_path: "./cda:\(element_name)") return find_or_create_provider(provider_data) } - class func find_or_create_provider(provider_hash: [String:Any], patient: CDAKPerson? = nil) -> CDAKProvider { + class func find_or_create_provider(_ provider_hash: [String:Any], patient: CDAKPerson? = nil) -> CDAKProvider { //see if we can find our provider by NPI - if let npi = provider_hash["npi"] as? String where npi != "" { + if let npi = provider_hash["npi"] as? String , npi != "" { if let a_provider = CDAKProvider.by_npi(npi) { return a_provider } } else { //if we have cda identifiers - if let cda_identifiers = provider_hash["cda_identifiers"] as? [CDAKCDAIdentifier] where cda_identifiers.count > 0 { + if let cda_identifiers = provider_hash["cda_identifiers"] as? [CDAKCDAIdentifier] , cda_identifiers.count > 0 { //try to find a Provider entry where the identifiers are common if let a_provider = CDAKGlobals.sharedInstance.CDAKProviders.filter({ p in p.cda_identifiers.filter({ id in cda_identifiers.contains(id) @@ -72,7 +72,7 @@ class CDAKImport_ProviderImportUtils { // the CDA identifier array, then written _over_ by the _real_ CDA Identifiers that the record pulls in from the XML // So - ordering (for the moment) matters - until I work around this in the provider NPI retrieval if let npi = provider_hash["npi"] { - provider.npi = String(npi) + provider.npi = String(describing: npi) } if let cda_identifiers = provider_hash["cda_identifiers"] as? [CDAKCDAIdentifier] { var filteredValues: [CDAKCDAIdentifier] = [CDAKCDAIdentifier]() @@ -85,7 +85,7 @@ class CDAKImport_ProviderImportUtils { } } //we're APPENDING since we don't want to remove the NPI CDA identifiers - provider.cda_identifiers.appendContentsOf(filteredValues) + provider.cda_identifiers.append(contentsOf: filteredValues) } if let addresses = provider_hash["addresses"] as? [CDAKAddress] { @@ -103,8 +103,8 @@ class CDAKImport_ProviderImportUtils { //# Returns nil if result is an empty string, block allows text munging of result if there is one - class func extract_data(subject: XMLElement, query: String) -> String? { - if let result = subject.xpath(query).first?.stringValue where result != "" { + class func extract_data(_ subject: XMLElement, query: String) -> String? { + if let result = subject.xpath(query).first?.stringValue , result != "" { return result } return nil diff --git a/CDAKit/health-data-standards/lib/models/address.swift b/CDAKit/health-data-standards/lib/models/address.swift index f215aac..21d9580 100644 --- a/CDAKit/health-data-standards/lib/models/address.swift +++ b/CDAKit/health-data-standards/lib/models/address.swift @@ -11,35 +11,35 @@ import Foundation /** Represents a physical address */ -public class CDAKAddress: NSObject, CDAKJSONInstantiable { +open class CDAKAddress: NSObject, CDAKJSONInstantiable { //Pointer back to parent record weak var record: CDAKRecord? // MARK: CDA properties ///Street - public var street: [String] = [String]() + open var street: [String] = [String]() ///City - public var city: String? + open var city: String? ///State - public var state: String? + open var state: String? ///Zip code - public var zip: String? + open var zip: String? ///Country code - public var country: String? + open var country: String? /** HL7 Address Use codes HL7 OID: 2.16.840.1.113883.5.1119 [Reference] (https://www.hl7.org/fhir/v3/AddressUse/index.html) */ - public var use: String? + open var use: String? /** Determines whether the address is empty */ - public var is_empty: Bool { + open var is_empty: Bool { - let someText: String = "\(street.flatMap({$0}).joinWithSeparator(""))\(city ?? "")\(state ?? "")\(zip ?? "")\(country ?? "")".stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) + let someText: String = "\(street.flatMap({$0}).joined(separator: ""))\(city ?? "")\(state ?? "")\(zip ?? "")\(country ?? "")".trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) if someText.characters.count > 0 { return false @@ -71,7 +71,7 @@ public class CDAKAddress: NSObject, CDAKJSONInstantiable { } ///Do not use - will be removed. Was used in HDS Ruby. - private func initFromEventList(event: [String:Any?]) { + fileprivate func initFromEventList(_ event: [String:Any?]) { for (key, value) in event { CDAKUtility.setProperty(self, property: key, value: value) } @@ -79,7 +79,7 @@ public class CDAKAddress: NSObject, CDAKJSONInstantiable { // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return "CDAKAddress => street: \(street), city: \(city), state: \(state), zip: \(zip), country: \(country), use: \(use)" } @@ -91,23 +91,23 @@ extension CDAKAddress: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] if street.count > 0 { - dict["street"] = street + dict["street"] = street as AnyObject? } if let city = city { - dict["city"] = city + dict["city"] = city as AnyObject? } if let state = state { - dict["state"] = state + dict["state"] = state as AnyObject? } if let zip = zip { - dict["zip"] = zip + dict["zip"] = zip as AnyObject? } if let country = country { - dict["country"] = country + dict["country"] = country as AnyObject? } if let use = use { - dict["use"] = use + dict["use"] = use as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/allergy.swift b/CDAKit/health-data-standards/lib/models/allergy.swift index 489edd3..6e75515 100644 --- a/CDAKit/health-data-standards/lib/models/allergy.swift +++ b/CDAKit/health-data-standards/lib/models/allergy.swift @@ -14,15 +14,15 @@ import Mustache /** Represents an Allergy entry */ -public class CDAKAllergy: CDAKEntry { +open class CDAKAllergy: CDAKEntry { // MARK: CDA properties ///type - public var type: CDAKCodedEntries = CDAKCodedEntries() + open var type: CDAKCodedEntries = CDAKCodedEntries() ///reaction - public var reaction: CDAKEntryDetail?// = CDAKCodedEntries() //flat code list + open var reaction: CDAKEntryDetail?// = CDAKCodedEntries() //flat code list ///severity - public var severity: CDAKEntryDetail?// = CDAKCodedEntries() //flat code list + open var severity: CDAKEntryDetail?// = CDAKCodedEntries() //flat code list // MARK: - Initializers public init(type:CDAKCodedEntries, reaction: CDAKEntryDetail? = nil, severity: CDAKEntryDetail? = nil) { @@ -65,7 +65,7 @@ extension CDAKAllergy { var dict = super.jsonDict if type.count > 0 { - dict["type"] = type.codes.map({$0.jsonDict}) + dict["type"] = type.codes.map({$0.jsonDict}) as AnyObject? } // if reaction.count > 0 { // dict["reaction"] = reaction.codes.map({$0.jsonDict}) @@ -74,10 +74,10 @@ extension CDAKAllergy { // dict["severity"] = severity.codes.map({$0.jsonDict}) // } if let reaction = reaction { - dict["reaction"] = reaction.jsonDict + dict["reaction"] = reaction.jsonDict as AnyObject? } if let severity = severity { - dict["severity"] = severity.jsonDict + dict["severity"] = severity.jsonDict as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/care_goal.swift b/CDAKit/health-data-standards/lib/models/care_goal.swift index d580f6f..ceb5ab8 100644 --- a/CDAKit/health-data-standards/lib/models/care_goal.swift +++ b/CDAKit/health-data-standards/lib/models/care_goal.swift @@ -12,13 +12,13 @@ import Mustache /** Represents a Care Goal. May be any of a variety of entries. */ -public class CDAKCareGoal: CDAKEntry { +open class CDAKCareGoal: CDAKEntry { // MARK: CDA properties ///Relaeted To (coded) - public var related_to: CDAKCodedEntries = CDAKCodedEntries() + open var related_to: CDAKCodedEntries = CDAKCodedEntries() ///Target Outcome (coded) - public var target_outcome: CDAKCodedEntries = CDAKCodedEntries() + open var target_outcome: CDAKCodedEntries = CDAKCodedEntries() } @@ -41,10 +41,10 @@ extension CDAKCareGoal { var dict = super.jsonDict if related_to.count > 0 { - dict["related_to"] = related_to.jsonDict + dict["related_to"] = related_to.jsonDict as AnyObject? } if target_outcome.count > 0 { - dict["target_outcome"] = target_outcome.jsonDict + dict["target_outcome"] = target_outcome.jsonDict as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/cda_identifier.swift b/CDAKit/health-data-standards/lib/models/cda_identifier.swift index f8fa5fd..1780b25 100644 --- a/CDAKit/health-data-standards/lib/models/cda_identifier.swift +++ b/CDAKit/health-data-standards/lib/models/cda_identifier.swift @@ -37,20 +37,20 @@ Usually takes the form of a "root" (required) and an "extension" (identifier) (o ``` */ -public class CDAKCDAIdentifier: Equatable, Hashable, CDAKJSONInstantiable, CustomStringConvertible { +open class CDAKCDAIdentifier: Equatable, Hashable, CDAKJSONInstantiable, CustomStringConvertible { // MARK: CDA properties ///CDA Root - public var root: String? + open var root: String? ///CDA Extension - public var extension_id: String? + open var extension_id: String? - public var hashValue: Int { + open var hashValue: Int { return "\(root)\(extension_id)".hashValue } ///Attempts to return a simplified compound version of the Root and Extension - public var as_string: String { + open var as_string: String { get { var r = "" var e = "" @@ -66,7 +66,7 @@ public class CDAKCDAIdentifier: Equatable, Hashable, CDAKJSONInstantiable, Custo // MARK: Standard properties ///Debugging description - public var description: String { + open var description: String { return "CDAKCDAIdentifier => root: \(root), extension_id: \(extension_id)" } @@ -83,7 +83,7 @@ public class CDAKCDAIdentifier: Equatable, Hashable, CDAKJSONInstantiable, Custo } ///Do not use - will be removed. Was used in HDS Ruby. - private func initFromEventList(event: [String:Any?]) { + fileprivate func initFromEventList(_ event: [String:Any?]) { for (key, value) in event { CDAKUtility.setProperty(self, property: key, value: value) } @@ -116,12 +116,12 @@ extension CDAKCDAIdentifier: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if let root = root { - dict["root"] = root + dict["root"] = root as AnyObject? } if let extension_id = extension_id { - dict["extension"] = extension_id + dict["extension"] = extension_id as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/coded_result_value.swift b/CDAKit/health-data-standards/lib/models/coded_result_value.swift index 29cc1cd..35d9af0 100644 --- a/CDAKit/health-data-standards/lib/models/coded_result_value.swift +++ b/CDAKit/health-data-standards/lib/models/coded_result_value.swift @@ -11,19 +11,19 @@ import Foundation /** CDA Coded Result Value */ -public class CDAKCodedResultValue: CDAKResultValue, CDAKThingWithCodes { +open class CDAKCodedResultValue: CDAKResultValue, CDAKThingWithCodes { // MARK: CDA properties ///CDA description - public var item_description: String? + open var item_description: String? ///Any codes associated with the result value - public var codes: CDAKCodedEntries = CDAKCodedEntries() + open var codes: CDAKCodedEntries = CDAKCodedEntries() // MARK: Standard properties ///Debugging description - override public var description: String { - return "\(self.dynamicType) => attributes: \(attributes), time: \(time), start_time: \(start_time), end_time: \(end_time), item_description: \(item_description), codes: \(codes)" + override open var description: String { + return "\(type(of: self)) => attributes: \(attributes), time: \(time), start_time: \(start_time), end_time: \(end_time), item_description: \(item_description), codes: \(codes)" } } @@ -36,10 +36,10 @@ extension CDAKCodedResultValue { var dict = super.jsonDict if let item_description = item_description { - dict["description"] = item_description + dict["description"] = item_description as AnyObject? } if codes.count > 0 { - dict["codes"] = codes.codes.map({$0.jsonDict}) + dict["codes"] = codes.codes.map({$0.jsonDict}) as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/communication.swift b/CDAKit/health-data-standards/lib/models/communication.swift index 614b602..b891b11 100644 --- a/CDAKit/health-data-standards/lib/models/communication.swift +++ b/CDAKit/health-data-standards/lib/models/communication.swift @@ -12,10 +12,10 @@ import Foundation Communication Could represent provider to patient, etc. */ -public class CDAKCommunication: CDAKEntry { +open class CDAKCommunication: CDAKEntry { // MARK: CDA properties ///Direction of communication - public var direction: String? + open var direction: String? } extension CDAKCommunication { @@ -25,7 +25,7 @@ extension CDAKCommunication { var dict = super.jsonDict if let direction = direction { - dict["direction"] = direction + dict["direction"] = direction as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/condition.swift b/CDAKit/health-data-standards/lib/models/condition.swift index 7cbeab8..8878aa3 100644 --- a/CDAKit/health-data-standards/lib/models/condition.swift +++ b/CDAKit/health-data-standards/lib/models/condition.swift @@ -17,43 +17,43 @@ CDA Condition Most frequently considerd a "problem" or "diagnosis." */ -public class CDAKCondition: CDAKEntry { +open class CDAKCondition: CDAKEntry { // MARK: CDA properties ///Type - public var type : String? + open var type : String? ///Was this the cause of death? - public var cause_of_death : Bool? = false + open var cause_of_death : Bool? = false ///Time of death - public var time_of_death : Double? + open var time_of_death : Double? ///Priority, if available. "Primary," "Secondary," etc. in numeric form - public var priority : Int? + open var priority : Int? ///Name of condition - public var name : String? + open var name : String? ///Ordinality - public var ordinality : CDAKCodedEntries = CDAKCodedEntries() + open var ordinality : CDAKCodedEntries = CDAKCodedEntries() ///Severity - public var severity : CDAKCodedEntries = CDAKCodedEntries() //# Currently unsupported by any importers + open var severity : CDAKCodedEntries = CDAKCodedEntries() //# Currently unsupported by any importers ///Laterality - public var laterality : CDAKCodedEntries = CDAKCodedEntries() + open var laterality : CDAKCodedEntries = CDAKCodedEntries() ///Anatomical Taret - public var anatomical_target : CDAKCodedEntries = CDAKCodedEntries() + open var anatomical_target : CDAKCodedEntries = CDAKCodedEntries() ///Anatomical Location - public var anatomical_location : CDAKCodedEntries = CDAKCodedEntries() + open var anatomical_location : CDAKCodedEntries = CDAKCodedEntries() ///Age at onset (if documented) - public var age_at_onset: Int? //an actual age - like "20" + open var age_at_onset: Int? //an actual age - like "20" ///Treating provider (if documented) - public var treating_provider: [CDAKProvider] = [CDAKProvider]() + open var treating_provider: [CDAKProvider] = [CDAKProvider]() ///renders display version of code based on preferred code set - override public var code_display : String { + override open var code_display : String { return ViewHelper.code_display(self, options: ["preferred_code_sets":self.preferred_code_sets, "tag_name": "value", "extra_content": "xsi:type=\"CD\""]) } // MARK: Health-Data-Standards Functions ///Offset all dates - override func shift_dates(date_diff: Double) { + override func shift_dates(_ date_diff: Double) { super.shift_dates(date_diff) if let time_of_death = time_of_death { self.time_of_death = time_of_death + date_diff @@ -62,7 +62,7 @@ public class CDAKCondition: CDAKEntry { // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return super.description + " name: \(name), type: \(type), cause_of_death: \(cause_of_death), time_of_death: \(time_of_death), priority: \(priority), ordinality: \(ordinality), severity: \(severity), laterality: \(laterality), anatomical_target: \(anatomical_target), anatomical_location: \(anatomical_location)" } @@ -96,40 +96,40 @@ extension CDAKCondition { var dict = super.jsonDict if let type = type { - dict["type"] = type + dict["type"] = type as AnyObject? } if let cause_of_death = cause_of_death { - dict["cause_of_death"] = cause_of_death + dict["cause_of_death"] = cause_of_death as AnyObject? } if let time_of_death = time_of_death { - dict["time_of_death"] = time_of_death + dict["time_of_death"] = time_of_death as AnyObject? } if let priority = priority { - dict["priority"] = priority + dict["priority"] = priority as AnyObject? } if let name = name { - dict["name"] = name + dict["name"] = name as AnyObject? } if ordinality.count > 0 { - dict["ordinality"] = ordinality.codes.map({$0.jsonDict}) + dict["ordinality"] = ordinality.codes.map({$0.jsonDict}) as AnyObject? } if severity.count > 0 { - dict["severity"] = severity.codes.map({$0.jsonDict}) + dict["severity"] = severity.codes.map({$0.jsonDict}) as AnyObject? } if laterality.count > 0 { - dict["laterality"] = laterality.codes.map({$0.jsonDict}) + dict["laterality"] = laterality.codes.map({$0.jsonDict}) as AnyObject? } if anatomical_target.count > 0 { - dict["anatomical_target"] = anatomical_target.codes.map({$0.jsonDict}) + dict["anatomical_target"] = anatomical_target.codes.map({$0.jsonDict}) as AnyObject? } if anatomical_location.count > 0 { - dict["anatomical_location"] = anatomical_location.codes.map({$0.jsonDict}) + dict["anatomical_location"] = anatomical_location.codes.map({$0.jsonDict}) as AnyObject? } if let age_at_onset = age_at_onset { - dict["age_at_onset"] = age_at_onset + dict["age_at_onset"] = age_at_onset as AnyObject? } if treating_provider.count > 0 { - dict["treating_provider"] = treating_provider.map({$0.jsonDict}) + dict["treating_provider"] = treating_provider.map({$0.jsonDict}) as AnyObject? } diff --git a/CDAKit/health-data-standards/lib/models/date_shiftable.swift b/CDAKit/health-data-standards/lib/models/date_shiftable.swift index 685beaf..9044fe7 100644 --- a/CDAKit/health-data-standards/lib/models/date_shiftable.swift +++ b/CDAKit/health-data-standards/lib/models/date_shiftable.swift @@ -13,6 +13,6 @@ Protocol for date shifting functions */ protocol CDAKDateShiftable { ///Offset all dates by specified double - func shift_dates(date_diff: Double) + func shift_dates(_ date_diff: Double) } diff --git a/CDAKit/health-data-standards/lib/models/encounter.swift b/CDAKit/health-data-standards/lib/models/encounter.swift index 5af51f1..89c38af 100644 --- a/CDAKit/health-data-standards/lib/models/encounter.swift +++ b/CDAKit/health-data-standards/lib/models/encounter.swift @@ -15,35 +15,35 @@ Represents a CDA Encounter [Reference](http://www.cdapro.com/know/26178) */ -public class CDAKEncounter: CDAKEntry { +open class CDAKEncounter: CDAKEntry { // MARK: CDA properties /** CDA priorityCode [Reference](http://www.cdapro.com/know/25039) */ - public var admit_type: CDAKCodedEntries = CDAKCodedEntries() // :admit_type, type: Hash + open var admit_type: CDAKCodedEntries = CDAKCodedEntries() // :admit_type, type: Hash ///CDA dischargeDispositionCode - public var discharge_disposition: CDAKCodedEntries = CDAKCodedEntries() // :discharge_disposition, type: Hash + open var discharge_disposition: CDAKCodedEntries = CDAKCodedEntries() // :discharge_disposition, type: Hash ///Time of admission - public var admit_time: Double? // , as: :admit_time, type: Integer + open var admit_time: Double? // , as: :admit_time, type: Integer ///Time of discharge - public var discharge_time: Double? // :discharge_time, type: Integer + open var discharge_time: Double? // :discharge_time, type: Integer ///Principal diagnosis - public var principal_diagnosis: CDAKCodedEntries = CDAKCodedEntries() //:principal_diagnosis, type: Hash + open var principal_diagnosis: CDAKCodedEntries = CDAKCodedEntries() //:principal_diagnosis, type: Hash ///Diagnosis - public var diagnosis: CDAKCodedEntries = CDAKCodedEntries() + open var diagnosis: CDAKCodedEntries = CDAKCodedEntries() ///Transfer to - public var transfer_to: CDAKTransfer?//, class_name: "CDAKTransfer" + open var transfer_to: CDAKTransfer?//, class_name: "CDAKTransfer" ///Transfer from - public var transfer_from: CDAKTransfer?//, class_name: "CDAKTransfer" + open var transfer_from: CDAKTransfer?//, class_name: "CDAKTransfer" ///Facility - public var facility: CDAKFacility? + open var facility: CDAKFacility? ///Performer - public var performer: CDAKProvider? + open var performer: CDAKProvider? /** Indication @@ -52,12 +52,12 @@ public class CDAKEncounter: CDAKEntry { - Version 1.0: Not present - Version 1.0.1: Added as a full Entry. It contains a full problem, including dates, codes, etc. */ - public var indication: CDAKEntry? // type: Hash + open var indication: CDAKEntry? // type: Hash // MARK: Health-Data-Standards Functions ///Offset all dates by specified double - override func shift_dates(date_diff: Double) { + override func shift_dates(_ date_diff: Double) { super.shift_dates(date_diff) if let facility = facility { @@ -74,7 +74,7 @@ public class CDAKEncounter: CDAKEntry { // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return super.description + " , admit_type: \(admit_type), discharge_disposition: \(discharge_disposition), admit_time: \(admit_time), discharge_time: \(discharge_time), principal_diagnosis: \(principal_diagnosis), transfer_to: \(transfer_to), transfer_from: \(transfer_from), facility: \(facility), performer: \(performer)" } @@ -122,40 +122,40 @@ extension CDAKEncounter { var dict = super.jsonDict if admit_type.count > 0 { - dict["admit_type"] = admit_type.codes.map({$0.jsonDict}) + dict["admit_type"] = admit_type.codes.map({$0.jsonDict}) as AnyObject? } if discharge_disposition.count > 0 { - dict["discharge_disposition"] = discharge_disposition.codes.map({$0.jsonDict}) + dict["discharge_disposition"] = discharge_disposition.codes.map({$0.jsonDict}) as AnyObject? } if let admit_time = admit_time { - dict["admit_time"] = admit_time + dict["admit_time"] = admit_time as AnyObject? } if let discharge_time = discharge_time { - dict["discharge_time"] = discharge_time + dict["discharge_time"] = discharge_time as AnyObject? } if principal_diagnosis.count > 0 { - dict["principal_diagnosis"] = principal_diagnosis.codes.map({$0.jsonDict}) + dict["principal_diagnosis"] = principal_diagnosis.codes.map({$0.jsonDict}) as AnyObject? } if diagnosis.count > 0 { - dict["diagnosis"] = diagnosis.codes.map({$0.jsonDict}) + dict["diagnosis"] = diagnosis.codes.map({$0.jsonDict}) as AnyObject? } if let transfer_to = transfer_to { - dict["transfer_to"] = transfer_to.jsonDict + dict["transfer_to"] = transfer_to.jsonDict as AnyObject? } if let transfer_from = transfer_from { - dict["transfer_from"] = transfer_from.jsonDict + dict["transfer_from"] = transfer_from.jsonDict as AnyObject? } if let facility = facility { - dict["facility"] = facility.jsonDict + dict["facility"] = facility.jsonDict as AnyObject? } if let performer = performer { - dict["performer"] = performer.jsonDict + dict["performer"] = performer.jsonDict as AnyObject? } if let indication = indication { - dict["indication"] = indication.jsonDict + dict["indication"] = indication.jsonDict as AnyObject? } diff --git a/CDAKit/health-data-standards/lib/models/entry.swift b/CDAKit/health-data-standards/lib/models/entry.swift index fae82a4..dcb86f7 100644 --- a/CDAKit/health-data-standards/lib/models/entry.swift +++ b/CDAKit/health-data-standards/lib/models/entry.swift @@ -8,12 +8,32 @@ import Foundation import Mustache +fileprivate func < (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } +} + +fileprivate func > (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l > r + default: + return rhs < lhs + } +} + /** Root type of generic CDA Entry. All other "entry-like" types inherit from CDAKEntry */ -public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, CDAKThingWithTimes, CDAKJSONInstantiable, CDAKThingWithIdentifier { +open class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, CDAKThingWithTimes, CDAKJSONInstantiable, CDAKThingWithIdentifier { //Equatable, Hashable, @@ -31,10 +51,10 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, Like LOINC:12345 */ - public var codes: CDAKCodedEntries = CDAKCodedEntries() + open var codes: CDAKCodedEntries = CDAKCodedEntries() ///Type of CDA Entry if available - public var cda_identifier: CDAKCDAIdentifier? //, class_name: "CDAKCDAIdentifier", as: :cda_identifiable + open var cda_identifier: CDAKCDAIdentifier? //, class_name: "CDAKCDAIdentifier", as: :cda_identifiable //FIX_ME: - I changed the class to PhysicalQuantityResultValue here // the test cases all made it appear we're using that and not ResultValue /** @@ -44,60 +64,60 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, EX: Result of "Weight" is 160 lbs. */ - public var values = [CDAKResultValue]() //, class_name: "ResultValue"... and yet... it wants PhysicalQuantityResultValue - but in other places... ResultValue (PhysicalQuantityResultValue is a subclass of ResultValue) + open var values = [CDAKResultValue]() //, class_name: "ResultValue"... and yet... it wants PhysicalQuantityResultValue - but in other places... ResultValue (PhysicalQuantityResultValue is a subclass of ResultValue) ///CDA Reference - public var references = [CDAKReference]() // + open var references = [CDAKReference]() // ///CDA Provider preference - public var provider_preference = [CDAKEntry]() //, class_name: "CDAKEntry" + open var provider_preference = [CDAKEntry]() //, class_name: "CDAKEntry" ///CDA patient preference - public var patient_preference = [CDAKEntry]() //, class_name: "CDAKEntry" + open var patient_preference = [CDAKEntry]() //, class_name: "CDAKEntry" ///CDA Description - public var item_description: String? + open var item_description: String? ///CDA specifics - public var specifics: String? + open var specifics: String? ///A generalized "time" associated with the entry - public var time: Double? + open var time: Double? ///A start time associated with this entry - public var start_time: Double? + open var start_time: Double? ///an end time associated with this entry - public var end_time: Double? + open var end_time: Double? ///CDA status code - public var status_code : CDAKCodedEntries = CDAKCodedEntries() //, type: Hash + open var status_code : CDAKCodedEntries = CDAKCodedEntries() //, type: Hash /** CDA moodCode. Defaulted to "EVN" [Reference](http://www.cdapro.com/know/25027) */ - public var mood_code: String = "EVN" //, type: String, default: "EVN" + open var mood_code: String = "EVN" //, type: String, default: "EVN" ///CDA negation indicator. Is this a "negation" of the act? - public var negation_ind: Bool? = false //, as: :negation_ind, type: Boolean + open var negation_ind: Bool? = false //, as: :negation_ind, type: Boolean ///CDA negation reason - public var negation_reason : CDAKCodedEntries = CDAKCodedEntries()//, as: :negation_reason, type: Hash + open var negation_reason : CDAKCodedEntries = CDAKCodedEntries()//, as: :negation_reason, type: Hash ///CDA OID - public var oid: String? //, type: String + open var oid: String? //, type: String ///CDA Reason - public var reason: CDAKReason?//, type: Hash + open var reason: CDAKReason?//, type: Hash ///Comments support - public var comment: String? // not in original model, but found in some other CDAKEntry items like pregnancies + open var comment: String? // not in original model, but found in some other CDAKEntry items like pregnancies ///Version of entry - public var version: Int = 1 + open var version: Int = 1 ///id - public var id: String? + open var id: String? ///Date of entry creation - public var created_at = NSDate() + open var created_at = Date() ///Date of last entry update - public var updated_at = NSDate() + open var updated_at = Date() ///Allows you to provide a custom list of code set keys / tags to override the default behavior for this entry. All entries have defined preferred code sets like "SNOMED-CT" or "LOINC", but if you use a generic CDAKEntry, none are defined. You can use this to either completely override the default code sets supplied by the system or provide a specific set of preferred code sets for generic entries (as is required for things like an `Indication` within an `encounter` or `medication`. - public var explicit_preferred_code_sets : [String] = [] + open var explicit_preferred_code_sets : [String] = [] //Condition //method "builds" (new) object and reflects on properties (response to -> class, id) // any of the CDAKEntry types should have this - func add_reference(entry: CDAKEntry, type: String) { + func add_reference(_ entry: CDAKEntry, type: String) { let ref = CDAKReference(type: type, referenced_type: CDAKCommonUtility.classNameAsString(entry), referenced_id: entry.id, entry: entry) references.append(ref) //references.build(type: type, referenced_type: entry.class, referenced_id: entry.id) @@ -107,7 +127,7 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, // MARK: Health-Data-Standards Functions ///Convert times to CDA strings - func times_to_s(nil_string: String = "UNK") -> String { + func times_to_s(_ nil_string: String = "UNK") -> String { var ret = "" @@ -117,18 +137,18 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, ret = "\(start_string) - \(end_string)" } else if let time = time { //Time.at(time).utc.to_formatted_s(:long_ordinal) - return NSDate(timeIntervalSince1970: Double(time)).stringFormattedAsHDSDate + return Date(timeIntervalSince1970: Double(time)).stringFormattedAsHDSDate } return ret } ///Convert times to CDA strings - class func time_to_s(input_time: Double) -> String { + class func time_to_s(_ input_time: Double) -> String { //original code //Time.at(input_time).utc.to_formatted_s(:long_ordinal) - let date = NSDate(timeIntervalSince1970: NSTimeInterval(input_time)) + let date = Date(timeIntervalSince1970: TimeInterval(input_time)) let date_string = date.stringFormattedAsHDSDate return date_string @@ -175,7 +195,7 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, // I realize this is ugly - I'm trying to retain the initial code as much as possible, even where not "Swifty" ///CDA status string - public var status: String? { + open var status: String? { get { return status_legacy() } @@ -218,12 +238,12 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, - parameter scalar: the value. Anything we can convert to a String - parameter units: the units of the scalar value */ - public func set_value(scalar: Any?, units: String?) { + open func set_value(_ scalar: Any?, units: String?) { var a_scalar: String? if let val = scalar { //if we have an optional, unwrap it and attempt to make it a String - a_scalar = String(val) + a_scalar = String(describing: val) } let pq_value = CDAKPhysicalQuantityResultValue(scalar: a_scalar, units: units) @@ -236,7 +256,7 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, - parameter code_set: array of CodedEntries. Describe the values for code sets - returns: true / false whether the code is in the list of desired codes */ - func is_in_code_set(code_set: [CDAKCodedEntries]) -> Bool { + func is_in_code_set(_ code_set: [CDAKCodedEntries]) -> Bool { for entries in code_set { // for (key, entry) in entries { // if codes.findIntersectingCodes(forCodeSystem: key, matchingCodes: entry.codes)?.count > 0 { @@ -291,7 +311,7 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, } ///Offset all dates by specified double - func shift_dates(date_diff: Double) { + func shift_dates(_ date_diff: Double) { if let start_time = start_time { self.start_time = start_time + date_diff } @@ -354,17 +374,17 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, } ///Returns CDA identifier or fixed id if not present - public var identifier: AnyObject? { + open var identifier: AnyObject? { //FIX_ME: - not sure this whole "identifier" business is right here if let cda_identifier = cda_identifier { return cda_identifier } else { - return id + return id as AnyObject? } } ///Converts CDA identifier to string for use - public var identifier_as_string: String { + open var identifier_as_string: String { //FIX_ME:: this is a bad placeholder to deal with typing - I just need an "identifier" I can use as a key if let cda_identifier = cda_identifier { return cda_identifier.as_string @@ -377,7 +397,7 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, // MARK: Standard properties ///Internal object hash value - override public var hashValue: Int { + override open var hashValue: Int { //FIX_ME: - not using the hash - just using native properties var hv: Int @@ -387,7 +407,7 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, if values.count > 0 { hv = hv ^ "\(values)".hashValue } - if let start_time = start_time, end_time = end_time { + if let start_time = start_time, let end_time = end_time { hv = hv ^ start_time.hashValue hv = hv ^ end_time.hashValue } else { @@ -442,14 +462,14 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, } ///Do not use - will be removed. Was used in HDS Ruby. - private func initFromEventList(event: [String:Any?]) { + fileprivate func initFromEventList(_ event: [String:Any?]) { let ignore_props: [String] = ["code", "code_set", "value", "unit"] //in some cases we'll have key-value PAIRS like... // code_set / code // value / unit // these won't work for the single key-value entries - if let code = event["code"], code_set = event["code_set"] as? String { + if let code = event["code"], let code_set = event["code_set"] as? String { add_code(code, code_system: code_set) } @@ -471,8 +491,8 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, // MARK: Standard properties ///Debugging description - override public var description : String { - return "\(self.dynamicType) => codes: \(codes), cda_identifier: \(identifier_as_string), values: \(values), references: \(references), provider_preference: \(provider_preference), patient_preference: \(patient_preference), item_description: \(item_description), specifics: \(specifics), time: \(time), start_time: \(start_time), end_time: \(end_time), status_code: \(status_code), mood_code: \(mood_code), negation_ind: \(negation_ind), negation_reason: \(negation_reason), oid: \(oid), reason: \(reason), version: \(version), id: \(id), created_at: \(created_at), updated_at: \(updated_at)" + override open var description : String { + return "\(type(of: self)) => codes: \(codes), cda_identifier: \(identifier_as_string), values: \(values), references: \(references), provider_preference: \(provider_preference), patient_preference: \(patient_preference), item_description: \(item_description), specifics: \(specifics), time: \(time), start_time: \(start_time), end_time: \(end_time), status_code: \(status_code), mood_code: \(mood_code), negation_ind: \(negation_ind), negation_reason: \(negation_reason), oid: \(oid), reason: \(reason), version: \(version), id: \(id), created_at: \(created_at), updated_at: \(updated_at)" } } @@ -481,7 +501,7 @@ public class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, //new in Swift 2.x with NSObject // http://mgrebenets.github.io/swift/2015/06/21/equatable-nsobject-with-swift-2/ extension CDAKEntry { - override public func isEqual(object: AnyObject?) -> Bool { + override open func isEqual(_ object: Any?) -> Bool { if let rhs = object as? CDAKEntry { return hashValue == rhs.hashValue && CDAKCommonUtility.classNameAsString(self) == CDAKCommonUtility.classNameAsString(rhs) } @@ -502,7 +522,7 @@ extension CDAKEntry { return explicit_preferred_code_sets } - switch String(self.dynamicType) { + switch String(describing: type(of: self)) { case "CDAKAllergy": return ["RxNorm"] case "CDAKCareGoal": return ["SNOMED-CT"] case "CDAKCondition": return ["SNOMED-CT"] @@ -572,7 +592,7 @@ extension CDAKEntry { "statusCode_code": self.status != nil && self.status! == "resolved" ? Box("completed") : Box("active"), - "myType" : Box(String(self.dynamicType)), + "myType" : Box(String(describing: type(of: self))), "preferred_code_sets": Box(self.preferred_code_sets), "code_display": Box(code_display), @@ -588,80 +608,80 @@ extension CDAKEntry { ] } - override public var mustacheBox: MustacheBox { + override open var mustacheBox: MustacheBox { return Box(boxedValues) } } -extension CDAKEntry: CDAKJSONExportable { +extension CDAKEntry { // MARK: - JSON Generation ///Dictionary for JSON data public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] if codes.count > 0 { - dict["codes"] = codes.codes.map({$0.jsonDict}) + dict["codes"] = codes.codes.map({$0.jsonDict}) as AnyObject? } if let cda_identifier = cda_identifier { - dict["cda_identifier"] = cda_identifier.jsonDict + dict["cda_identifier"] = cda_identifier.jsonDict as AnyObject? } if values.count > 0 { - dict["values"] = values.map({$0.jsonDict}) + dict["values"] = values.map({$0.jsonDict}) as AnyObject? } if references.count > 0 { - dict["references"] = references.map({$0.jsonDict}) + dict["references"] = references.map({$0.jsonDict}) as AnyObject? } if provider_preference.count > 0 { - dict["provider_preference"] = provider_preference.map({$0.jsonDict}) + dict["provider_preference"] = provider_preference.map({$0.jsonDict}) as AnyObject? } if patient_preference.count > 0 { - dict["patient_preference"] = patient_preference.map({$0.jsonDict}) + dict["patient_preference"] = patient_preference.map({$0.jsonDict}) as AnyObject? } if let item_description = item_description { - dict["description"] = item_description + dict["description"] = item_description as AnyObject? } if let specifics = specifics { - dict["specifics"] = specifics + dict["specifics"] = specifics as AnyObject? } if let time = time { - dict["time"] = time + dict["time"] = time as AnyObject? } if let start_time = start_time { - dict["start_time"] = start_time + dict["start_time"] = start_time as AnyObject? } if let end_time = end_time { - dict["end_time"] = end_time + dict["end_time"] = end_time as AnyObject? } if status_code.count > 0 { - dict["status_code"] = status_code.codes.map({$0.jsonDict}) + dict["status_code"] = status_code.codes.map({$0.jsonDict}) as AnyObject? } - dict["mood_code"] = mood_code + dict["mood_code"] = mood_code as AnyObject? if let negation_ind = negation_ind { - dict["negation_ind"] = negation_ind + dict["negation_ind"] = negation_ind as AnyObject? } if negation_reason.count > 0 { - dict["negation_reason"] = negation_reason.codes.map({$0.jsonDict}) + dict["negation_reason"] = negation_reason.codes.map({$0.jsonDict}) as AnyObject? } if let oid = oid { - dict["oid"] = oid + dict["oid"] = oid as AnyObject? } if let reason = reason { - dict["reason"] = reason.jsonDict + dict["reason"] = reason.jsonDict as AnyObject? } if let comment = comment { - dict["comment"] = comment + dict["comment"] = comment as AnyObject? } - dict["version"] = version + dict["version"] = version as AnyObject? if let id = id { - dict["id"] = id + dict["id"] = id as AnyObject? } - dict["created_at"] = created_at.description - dict["updated_at"] = updated_at.description + dict["created_at"] = created_at.description as AnyObject? + dict["updated_at"] = updated_at.description as AnyObject? return dict } diff --git a/CDAKit/health-data-standards/lib/models/entry_detail.swift b/CDAKit/health-data-standards/lib/models/entry_detail.swift index dceb895..1cbf330 100644 --- a/CDAKit/health-data-standards/lib/models/entry_detail.swift +++ b/CDAKit/health-data-standards/lib/models/entry_detail.swift @@ -15,18 +15,18 @@ There is a recurring need to capture entry-like things witin an entry. Instead //this is probably a mistake... but we can change this later if we need to - public class CDAKEntryDetail: CDAKThingWithCodes, CDAKThingWithTimes, CDAKThingWithIdentifier, CustomStringConvertible { + open class CDAKEntryDetail: CDAKThingWithCodes, CDAKThingWithTimes, CDAKThingWithIdentifier, CustomStringConvertible { // MARK: CDA properties ///A generalized "time" associated with the entry - public var time: Double? + open var time: Double? ///A start time associated with this entry - public var start_time: Double? + open var start_time: Double? ///an end time associated with this entry - public var end_time: Double? + open var end_time: Double? ///Type of CDA Entry if available - public var cda_identifier: CDAKCDAIdentifier? //, class_name: "CDAKCDAIdentifier", as: :cda_identifiable + open var cda_identifier: CDAKCDAIdentifier? //, class_name: "CDAKCDAIdentifier", as: :cda_identifiable /** Core coded entries that represent any "meaning" behind the entry @@ -35,19 +35,19 @@ There is a recurring need to capture entry-like things witin an entry. Instead Like LOINC:12345 */ - public var codes: CDAKCodedEntries = CDAKCodedEntries() + open var codes: CDAKCodedEntries = CDAKCodedEntries() // MARK: Standard properties ///Internal object hash value - public var hashValue: Int { + open var hashValue: Int { //FIX_ME: - not using the hash - just using native properties var hv: Int hv = "\(codes)".hashValue - if let start_time = start_time, end_time = end_time { + if let start_time = start_time, let end_time = end_time { hv = hv ^ start_time.hashValue hv = hv ^ end_time.hashValue } else { @@ -59,8 +59,8 @@ There is a recurring need to capture entry-like things witin an entry. Instead // MARK: Standard properties ///Debugging description - public var description : String { - return "\(self.dynamicType) => codes: \(codes), cda_identifier: \(cda_identifier), time: \(time), start_time: \(start_time), end_time: \(end_time)" + open var description : String { + return "\(type(of: self)) => codes: \(codes), cda_identifier: \(cda_identifier), time: \(time), start_time: \(start_time), end_time: \(end_time)" } } @@ -96,20 +96,20 @@ extension CDAKEntryDetail: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if codes.count > 0 { - dict["codes"] = codes.codes.map({$0.jsonDict}) + dict["codes"] = codes.codes.map({$0.jsonDict}) as AnyObject? } if let cda_identifier = cda_identifier { - dict["cda_identifier"] = cda_identifier.jsonDict + dict["cda_identifier"] = cda_identifier.jsonDict as AnyObject? } if let time = time { - dict["time"] = time + dict["time"] = time as AnyObject? } if let start_time = start_time { - dict["start_time"] = start_time + dict["start_time"] = start_time as AnyObject? } if let end_time = end_time { - dict["end_time"] = end_time + dict["end_time"] = end_time as AnyObject? } return dict } diff --git a/CDAKit/health-data-standards/lib/models/facility.swift b/CDAKit/health-data-standards/lib/models/facility.swift index 8002c56..c04992a 100644 --- a/CDAKit/health-data-standards/lib/models/facility.swift +++ b/CDAKit/health-data-standards/lib/models/facility.swift @@ -14,21 +14,21 @@ import Foundation /** CDA Facility */ -public class CDAKFacility: CDAKEntry { +open class CDAKFacility: CDAKEntry { // MARK: CDA properties ///Facility name - public var name: String? + open var name: String? ///Facility addresses - public var addresses = [CDAKAddress]() //, as: :locatable + open var addresses = [CDAKAddress]() //, as: :locatable ///Facility telecoms - public var telecoms = [CDAKTelecom]() //, as: :contactable + open var telecoms = [CDAKTelecom]() //, as: :contactable // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return super.description + " name: \(name), addresss: \(addresses), telecoms: \(telecoms)" } @@ -41,13 +41,13 @@ extension CDAKFacility { var dict = super.jsonDict if let name = name { - dict["name"] = name + dict["name"] = name as AnyObject? } if addresses.count > 0 { - dict["addresses"] = addresses.map({$0.jsonDict}) + dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } if telecoms.count > 0 { - dict["telecoms"] = telecoms.map({$0.jsonDict}) + dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/family_history.swift b/CDAKit/health-data-standards/lib/models/family_history.swift index 3d89e49..72c01fe 100644 --- a/CDAKit/health-data-standards/lib/models/family_history.swift +++ b/CDAKit/health-data-standards/lib/models/family_history.swift @@ -11,13 +11,13 @@ import Foundation /** CDA Family History */ -public class CDAKFamilyHistory: CDAKEntry { +open class CDAKFamilyHistory: CDAKEntry { // MARK: CDA properties ///CDA relationship to patient - public var relationshipToPatient = [String:String]() + open var relationshipToPatient = [String:String]() ///CDA onset age - public var onsetAge = [String:String]() + open var onsetAge = [String:String]() } @@ -28,12 +28,12 @@ extension CDAKFamilyHistory { var dict = super.jsonDict if relationshipToPatient.count > 0 { - dict["relationshipToPatient"] = relationshipToPatient + dict["relationshipToPatient"] = relationshipToPatient as AnyObject? } if onsetAge.count > 0 { - dict["onsetAge"] = onsetAge + dict["onsetAge"] = onsetAge as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/fulfillment_history.swift b/CDAKit/health-data-standards/lib/models/fulfillment_history.swift index 36029cb..7a3cc4f 100644 --- a/CDAKit/health-data-standards/lib/models/fulfillment_history.swift +++ b/CDAKit/health-data-standards/lib/models/fulfillment_history.swift @@ -12,27 +12,27 @@ import Foundation /** CDA Fulfillment History */ -public class CDAKFulfillmentHistory: CDAKEntry { +open class CDAKFulfillmentHistory: CDAKEntry { // MARK: CDA properties ///Prescription number - public var prescription_number: String? //, as: :prescription_number, type: String + open var prescription_number: String? //, as: :prescription_number, type: String ///Dispense Date - public var dispense_date: Double? //, as: :dispense_date, type: Integer + open var dispense_date: Double? //, as: :dispense_date, type: Integer ///Quantity dispensed - public var quantity_dispensed = CDAKValueAndUnit() //, as: :quantity_dispensed, type: Hash + open var quantity_dispensed = CDAKValueAndUnit() //, as: :quantity_dispensed, type: Hash ///Fill number if available - public var fill_number: Int? //, as: :fill_number, type: Integer + open var fill_number: Int? //, as: :fill_number, type: Integer ///Fill status - public var fill_status: String? //, as: :fill_status, type: String + open var fill_status: String? //, as: :fill_status, type: String ///Ordering provider - public var provider: CDAKProvider? + open var provider: CDAKProvider? // MARK: Health-Data-Standards Functions ///Offset all dates by specified double - override func shift_dates(date_diff: Double) { + override func shift_dates(_ date_diff: Double) { super.shift_dates(date_diff) @@ -43,7 +43,7 @@ public class CDAKFulfillmentHistory: CDAKEntry { // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return super.description + " , prescription_number: \(prescription_number), dispense_date: \(dispense_date), fill_number: \(fill_number), fill_status: \(fill_status), quantity_dispensed: \(quantity_dispensed)" } @@ -56,24 +56,24 @@ extension CDAKFulfillmentHistory { var dict = super.jsonDict if let prescription_number = prescription_number { - dict["prescription_number"] = prescription_number + dict["prescription_number"] = prescription_number as AnyObject? } if quantity_dispensed.jsonDict.count > 0 { - dict["quantity_dispensed"] = quantity_dispensed.jsonDict + dict["quantity_dispensed"] = quantity_dispensed.jsonDict as AnyObject? } if let dispense_date = dispense_date { - dict["dispense_date"] = dispense_date + dict["dispense_date"] = dispense_date as AnyObject? } if let fill_number = fill_number { - dict["fill_number"] = fill_number + dict["fill_number"] = fill_number as AnyObject? } if let fill_status = fill_status { - dict["fill_status"] = fill_status + dict["fill_status"] = fill_status as AnyObject? } if let provider = provider { - dict["provider"] = provider.jsonDict + dict["provider"] = provider.jsonDict as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/functional_status.swift b/CDAKit/health-data-standards/lib/models/functional_status.swift index 2ee5e1e..412121a 100644 --- a/CDAKit/health-data-standards/lib/models/functional_status.swift +++ b/CDAKit/health-data-standards/lib/models/functional_status.swift @@ -17,15 +17,15 @@ Additionally, there is a mismatch between the data needed to calculate Stage 2 M To avoid this, the patient sumamry style functional status has been "flattened" into this class. This model supports the information needed to calculate Stage 2 MU CQMs. If importers are created from C32 or CCDA, the information can be stored here, but it will be a lossy transformation. */ -public class CDAKFunctionalStatus: CDAKEntry { +open class CDAKFunctionalStatus: CDAKEntry { // MARK: CDA properties /// Either "condition" or "result" - public var type: String? + open var type: String? /// A coded value. Like a code for patient supplied. - public var source: CDAKCodedEntries = CDAKCodedEntries() + open var source: CDAKCodedEntries = CDAKCodedEntries() } @@ -37,12 +37,12 @@ extension CDAKFunctionalStatus { var dict = super.jsonDict if let type = type { - dict["type"] = type + dict["type"] = type as AnyObject? } if source.count > 0 { - dict["source"] = source.jsonDict + dict["source"] = source.jsonDict as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/guarantor.swift b/CDAKit/health-data-standards/lib/models/guarantor.swift index c6b6895..5daacca 100644 --- a/CDAKit/health-data-standards/lib/models/guarantor.swift +++ b/CDAKit/health-data-standards/lib/models/guarantor.swift @@ -13,19 +13,19 @@ import Foundation CDA Guarantor. Individual legally responsible for all patient charges */ -public class CDAKGuarantor: CDAKEntry { +open class CDAKGuarantor: CDAKEntry { // MARK: CDA properties ///Organization - public var organization: CDAKOrganization? + open var organization: CDAKOrganization? ///Person - public var person: CDAKPerson? + open var person: CDAKPerson? // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return super.description + " person: \(person), organization: \(organization)" } @@ -38,12 +38,12 @@ extension CDAKGuarantor { var dict = super.jsonDict if let organization = organization { - dict["organization"] = organization.jsonDict + dict["organization"] = organization.jsonDict as AnyObject? } if let person = person { - dict["person"] = person.jsonDict + dict["person"] = person.jsonDict as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/immunization.swift b/CDAKit/health-data-standards/lib/models/immunization.swift index 001db84..ed9a0cd 100644 --- a/CDAKit/health-data-standards/lib/models/immunization.swift +++ b/CDAKit/health-data-standards/lib/models/immunization.swift @@ -10,27 +10,27 @@ import Foundation /** Record of immunization */ -public class CDAKImmunization: CDAKEntry { +open class CDAKImmunization: CDAKEntry { // MARK: CDA properties ///Vaccine series number - public var series_number: Int? //, type: Integer + open var series_number: Int? //, type: Integer ///Reaction to vaccine - public var reaction: CDAKCodedEntries = CDAKCodedEntries() //, type: Hash + open var reaction: CDAKCodedEntries = CDAKCodedEntries() //, type: Hash ///Provider who performed administration - public var performer: CDAKProvider? + open var performer: CDAKProvider? ///Vaccine medication product - public var medication_product: CDAKMedication? + open var medication_product: CDAKMedication? ///Was this immunization refused by the patient? - public var refusal_ind: Bool? { + open var refusal_ind: Bool? { get { return negation_ind } set (value) { negation_ind = value } } ///If the patient refused the vaccine, why did they refuse? - public var refusal_reason: CDAKCodedEntries { + open var refusal_reason: CDAKCodedEntries { get {return negation_reason } set (value) {negation_reason = value} } @@ -44,16 +44,16 @@ extension CDAKImmunization { var dict = super.jsonDict if let series_number = series_number { - dict["series_number"] = series_number + dict["series_number"] = series_number as AnyObject? } if reaction.count > 0 { - dict["reaction"] = reaction.codes.map({$0.jsonDict}) + dict["reaction"] = reaction.codes.map({$0.jsonDict}) as AnyObject? } if let performer = performer { - dict["performer"] = performer.jsonDict + dict["performer"] = performer.jsonDict as AnyObject? } if let medication_product = medication_product { - dict["medication_product"] = medication_product.jsonDict + dict["medication_product"] = medication_product.jsonDict as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/insurance_provider.swift b/CDAKit/health-data-standards/lib/models/insurance_provider.swift index d329c90..0ecb419 100644 --- a/CDAKit/health-data-standards/lib/models/insurance_provider.swift +++ b/CDAKit/health-data-standards/lib/models/insurance_provider.swift @@ -10,31 +10,31 @@ import Foundation /** Insurance Provider */ -public class CDAKInsuranceProvider: CDAKEntry { +open class CDAKInsuranceProvider: CDAKEntry { // MARK: CDA properties ///Payer (insurance provider) - public var payer: CDAKOrganization? //, class_name: "CDAKOrganization" + open var payer: CDAKOrganization? //, class_name: "CDAKOrganization" ///Insurance guarantor - public var guarantors = [CDAKGuarantor]()//, class_name: "CDAKGuarantor" + open var guarantors = [CDAKGuarantor]()//, class_name: "CDAKGuarantor" ///Insurance subscriber - public var subscriber: CDAKPerson? //, class_name: "CDAKPerson" + open var subscriber: CDAKPerson? //, class_name: "CDAKPerson" ///Type - public var type: String? + open var type: String? ///Member ID - public var member_id: String? + open var member_id: String? ///Relationship - public var relationship : CDAKCodedEntries = CDAKCodedEntries() //, type: Hash + open var relationship : CDAKCodedEntries = CDAKCodedEntries() //, type: Hash ///Financial responsibility type - public var financial_responsibility_type : CDAKCodedEntries = CDAKCodedEntries() //, type: Hash + open var financial_responsibility_type : CDAKCodedEntries = CDAKCodedEntries() //, type: Hash ///Name - public var name: String? + open var name: String? // MARK: Health-Data-Standards Functions ///Offset all dates by specified double - override func shift_dates(date_diff: Double) { + override func shift_dates(_ date_diff: Double) { super.shift_dates(date_diff) for g in guarantors { @@ -44,7 +44,7 @@ public class CDAKInsuranceProvider: CDAKEntry { // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return super.description + ", name: \(name), type: \(type), member_id: \(member_id), relationship: \(relationship), financial_responsibility_type: \(financial_responsibility_type), financial_responsibility_type: \(financial_responsibility_type), payer: \(payer), guarantors: \(guarantors), subscriber: \(subscriber)" } @@ -58,27 +58,27 @@ extension CDAKInsuranceProvider { var dict = super.jsonDict if let payer = payer { - dict["payer"] = payer.jsonDict + dict["payer"] = payer.jsonDict as AnyObject? } if guarantors.count > 0 { - dict["guarantors"] = guarantors.map({$0.jsonDict}) + dict["guarantors"] = guarantors.map({$0.jsonDict}) as AnyObject? } if let type = type { - dict["type"] = type + dict["type"] = type as AnyObject? } if let member_id = member_id { - dict["member_id"] = member_id + dict["member_id"] = member_id as AnyObject? } if relationship.count > 0 { - dict["relationship"] = relationship.codes.map({$0.jsonDict}) + dict["relationship"] = relationship.codes.map({$0.jsonDict}) as AnyObject? } if financial_responsibility_type.count > 0 { - dict["financial_responsibility_type"] = financial_responsibility_type.codes.map({$0.jsonDict}) + dict["financial_responsibility_type"] = financial_responsibility_type.codes.map({$0.jsonDict}) as AnyObject? } if let name = name { - dict["name"] = name + dict["name"] = name as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/lab_result.swift b/CDAKit/health-data-standards/lib/models/lab_result.swift index b1e2d61..82987d9 100644 --- a/CDAKit/health-data-standards/lib/models/lab_result.swift +++ b/CDAKit/health-data-standards/lib/models/lab_result.swift @@ -10,26 +10,26 @@ import Foundation /** CDA template for "result-like" things. Primarily lab results. */ -public class CDAKLabResult: CDAKEntry { +open class CDAKLabResult: CDAKEntry { // MARK: CDA properties ///reference range for the result - public var reference_range: String? //as reference_range + open var reference_range: String? //as reference_range ///fixed reference high - public var reference_range_high: String? //as reference_range_high + open var reference_range_high: String? //as reference_range_high ///fixed reference low - public var reference_range_low: String? //as reference_range_low + open var reference_range_low: String? //as reference_range_low ///Interpretation (coded form) - public var interpretation: CDAKCodedEntries = CDAKCodedEntries() + open var interpretation: CDAKCodedEntries = CDAKCodedEntries() ///Reaction - public var reaction: CDAKCodedEntries = CDAKCodedEntries() + open var reaction: CDAKCodedEntries = CDAKCodedEntries() ///Method - public var method: CDAKCodedEntries = CDAKCodedEntries() + open var method: CDAKCodedEntries = CDAKCodedEntries() // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return super.description + " reference_range: \(reference_range), reference_range_high: \(reference_range_high), reference_range_low: \(reference_range_low), interpretation: \(interpretation), reaction: \(reaction), method: \(method)" } @@ -43,26 +43,26 @@ extension CDAKLabResult { var dict = super.jsonDict if let reference_range = reference_range { - dict["reference_range"] = reference_range + dict["reference_range"] = reference_range as AnyObject? } if let reference_range_high = reference_range_high { - dict["reference_range_high"] = reference_range_high + dict["reference_range_high"] = reference_range_high as AnyObject? } if let reference_range_low = reference_range_low { - dict["reference_range_low"] = reference_range_low + dict["reference_range_low"] = reference_range_low as AnyObject? } if interpretation.count > 0 { - dict["interpretation"] = interpretation.codes.map({$0.jsonDict}) + dict["interpretation"] = interpretation.codes.map({$0.jsonDict}) as AnyObject? } if reaction.count > 0 { - dict["reaction"] = reaction.codes.map({$0.jsonDict}) + dict["reaction"] = reaction.codes.map({$0.jsonDict}) as AnyObject? } if method.count > 0 { - dict["method"] = method.codes.map({$0.jsonDict}) + dict["method"] = method.codes.map({$0.jsonDict}) as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/medical_equipment.swift b/CDAKit/health-data-standards/lib/models/medical_equipment.swift index f6d1bf1..50fc166 100644 --- a/CDAKit/health-data-standards/lib/models/medical_equipment.swift +++ b/CDAKit/health-data-standards/lib/models/medical_equipment.swift @@ -10,25 +10,25 @@ import Foundation /** CDA Medical Equipment */ -public class CDAKMedicalEquipment: CDAKEntry { +open class CDAKMedicalEquipment: CDAKEntry { // MARK: CDA properties ///Device manufacturer - public var manufacturer: String? + open var manufacturer: String? ///Anatomical Structure - public var anatomical_structure: CDAKCodedEntries = CDAKCodedEntries() //, as: :anatomical_structure, type: Hash + open var anatomical_structure: CDAKCodedEntries = CDAKCodedEntries() //, as: :anatomical_structure, type: Hash ///Time of device removal - public var removal_time: Double? //, as: :removal_time, type: Integer + open var removal_time: Double? //, as: :removal_time, type: Integer ///Anatomical approach - public var anatomical_approach: CDAKCodedEntries = CDAKCodedEntries() + open var anatomical_approach: CDAKCodedEntries = CDAKCodedEntries() ///Reaction - public var reaction: CDAKCodedEntries = CDAKCodedEntries() + open var reaction: CDAKCodedEntries = CDAKCodedEntries() // MARK: Health-Data-Standards Functions ///Offset all dates by specified double - override func shift_dates(date_diff: Double) { + override func shift_dates(_ date_diff: Double) { super.shift_dates(date_diff) if let removal_time = removal_time { @@ -46,22 +46,22 @@ extension CDAKMedicalEquipment { var dict = super.jsonDict if let manufacturer = manufacturer { - dict["manufacturer"] = manufacturer + dict["manufacturer"] = manufacturer as AnyObject? } if let removal_time = removal_time { - dict["removal_time"] = removal_time + dict["removal_time"] = removal_time as AnyObject? } if anatomical_structure.count > 0 { - dict["anatomical_structure"] = anatomical_structure.codes.map({$0.jsonDict}) + dict["anatomical_structure"] = anatomical_structure.codes.map({$0.jsonDict}) as AnyObject? } if anatomical_approach.count > 0 { - dict["anatomical_approach"] = anatomical_approach.codes.map({$0.jsonDict}) + dict["anatomical_approach"] = anatomical_approach.codes.map({$0.jsonDict}) as AnyObject? } if reaction.count > 0 { - dict["reaction"] = reaction.codes.map({$0.jsonDict}) + dict["reaction"] = reaction.codes.map({$0.jsonDict}) as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/medication.swift b/CDAKit/health-data-standards/lib/models/medication.swift index 63a9f4a..4546b1c 100644 --- a/CDAKit/health-data-standards/lib/models/medication.swift +++ b/CDAKit/health-data-standards/lib/models/medication.swift @@ -12,40 +12,40 @@ import Mustache /** Medication */ -public class CDAKMedication: CDAKEntry { +open class CDAKMedication: CDAKEntry { // MARK: CDA properties ///Timing of medication administration - public var administration_timing: CDAKMedicationAdministrationTiming = CDAKMedicationAdministrationTiming() + open var administration_timing: CDAKMedicationAdministrationTiming = CDAKMedicationAdministrationTiming() ///Free text signature or text - public var free_text_sig: String? + open var free_text_sig: String? ///Dosage information (doseQuantity) - public var dose = CDAKValueAndUnit() + open var dose = CDAKValueAndUnit() ///Rate information (rateQuantity) - public var rate = CDAKValueAndUnit() + open var rate = CDAKValueAndUnit() ///Type of medication - public var type_of_medication: CDAKCodedEntries = CDAKCodedEntries() // as: :type_of_medication // type: Hash + open var type_of_medication: CDAKCodedEntries = CDAKCodedEntries() // as: :type_of_medication // type: Hash ///Status of medication - public var status_of_medication: CDAKCodedEntries = CDAKCodedEntries() // as: :status_of_medication // type: Hash + open var status_of_medication: CDAKCodedEntries = CDAKCodedEntries() // as: :status_of_medication // type: Hash ///Fulfillment history (multiple possible) - public var fulfillment_history = [CDAKFulfillmentHistory]() // class_name: 'CDAKFulfillmentHistory' + open var fulfillment_history = [CDAKFulfillmentHistory]() // class_name: 'CDAKFulfillmentHistory' ///Order information (multiplepossible) - public var order_information = [CDAKOrderInformation]() // class_name: 'CDAKOrderInformation' + open var order_information = [CDAKOrderInformation]() // class_name: 'CDAKOrderInformation' ///Route of administration - public var route: CDAKCodedEntries = CDAKCodedEntries() // type: Hash + open var route: CDAKCodedEntries = CDAKCodedEntries() // type: Hash ///Anatomical approach - public var anatomical_approach: CDAKCodedEntries = CDAKCodedEntries() // type: Hash + open var anatomical_approach: CDAKCodedEntries = CDAKCodedEntries() // type: Hash //go take a look at the CDA CDAKMedication importer - it appears this is a hash of numerator / denominator entries that then have futher scalar value entries inside // not entirely clear what we'd really do with these except for far more complex inpatient examples ///Dosage restriction - public var dose_restriction: CDAKMedicationRestriction = CDAKMedicationRestriction() + open var dose_restriction: CDAKMedicationRestriction = CDAKMedicationRestriction() ///Fulfillment instructions (if supplied) - public var fulfillment_instructions: String? // as: :fulfillment_instructions // type: String + open var fulfillment_instructions: String? // as: :fulfillment_instructions // type: String /** Indication This is the problem that was the reason for the medication @@ -53,30 +53,30 @@ public class CDAKMedication: CDAKEntry { - Version 1.0: This was a CDAKCodedEntries - Version 1.0.1: This is now a full Entry. It contains a full problem, including dates, codes, etc. */ - public var indication: CDAKEntryDetail? // type: Hash + open var indication: CDAKEntryDetail? // type: Hash ///Precondition - public var precondition: CDAKCodedEntries = CDAKCodedEntries() // type: Hash + open var precondition: CDAKCodedEntries = CDAKCodedEntries() // type: Hash ///Product form - public var product_form: CDAKCodedEntries = CDAKCodedEntries() // as: :product_form // type: Hash + open var product_form: CDAKCodedEntries = CDAKCodedEntries() // as: :product_form // type: Hash ///Product vehicle - public var vehicle: CDAKCodedEntries = CDAKCodedEntries() // type: Hash + open var vehicle: CDAKCodedEntries = CDAKCodedEntries() // type: Hash ///Reaction to medication or administration - public var reaction: CDAKEntryDetail?//CDAKCodedEntries = CDAKCodedEntries() // type: Hash + open var reaction: CDAKEntryDetail?//CDAKCodedEntries = CDAKCodedEntries() // type: Hash ///severity - public var severity: CDAKEntryDetail?// = CDAKCodedEntries() //flat code list + open var severity: CDAKEntryDetail?// = CDAKCodedEntries() //flat code list ///Delivery method - public var delivery_method: CDAKCodedEntries = CDAKCodedEntries() // as: :delivery_method // type: Hash + open var delivery_method: CDAKCodedEntries = CDAKCodedEntries() // as: :delivery_method // type: Hash ///Patient instructions - public var patient_instructions: String? // as: :patient_instructions // type: String + open var patient_instructions: String? // as: :patient_instructions // type: String ///Dose indicator - public var dose_indicator: String? // as: :dose_indicator // type: String + open var dose_indicator: String? // as: :dose_indicator // type: String ///method - public var method: CDAKCodedEntries = CDAKCodedEntries() // type: Hash + open var method: CDAKCodedEntries = CDAKCodedEntries() // type: Hash ///Date as of which medication was active - public var active_datetime: Double? // type: Integer + open var active_datetime: Double? // type: Integer ///Date medication signed - public var signed_datetime: Double? // type: Integer + open var signed_datetime: Double? // type: Integer @@ -93,12 +93,12 @@ public class CDAKMedication: CDAKEntry { [Discussion](https://jira.oncprojectracking.org/browse/CQM-612) */ - public var cumulativeMedicationDuration: CDAKValueAndUnit? // = [String:String]() + open var cumulativeMedicationDuration: CDAKValueAndUnit? // = [String:String]() // MARK: Health-Data-Standards Functions ///Offset all dates by specified double - override func shift_dates(date_diff: Double) { + override func shift_dates(_ date_diff: Double) { super.shift_dates(date_diff) for fh in fulfillment_history { @@ -175,44 +175,44 @@ extension CDAKMedication { override public var jsonDict: [String: AnyObject] { var dict = super.jsonDict - if fulfillment_history.count > 0 { dict["fulfillment_history"] = fulfillment_history.map({$0.jsonDict}) } - if order_information.count > 0 { dict["order_information"] = order_information.map({$0.jsonDict}) } + if fulfillment_history.count > 0 { dict["fulfillment_history"] = fulfillment_history.map({$0.jsonDict}) as AnyObject? } + if order_information.count > 0 { dict["order_information"] = order_information.map({$0.jsonDict}) as AnyObject?} if let cumulativeMedicationDuration = cumulativeMedicationDuration { - dict["cumulativeMedicationDuration"] = cumulativeMedicationDuration.jsonDict + dict["cumulativeMedicationDuration"] = cumulativeMedicationDuration.jsonDict as AnyObject? } - if anatomical_approach.count > 0 { dict["anatomical_approach"] = anatomical_approach.codes.map({$0.jsonDict}) } - if delivery_method.count > 0 { dict["delivery_method"] = delivery_method.codes.map({$0.jsonDict}) } + if anatomical_approach.count > 0 { dict["anatomical_approach"] = anatomical_approach.codes.map({$0.jsonDict}) as AnyObject?} + if delivery_method.count > 0 { dict["delivery_method"] = delivery_method.codes.map({$0.jsonDict}) as AnyObject?} if let indication = indication { - dict["indication"] = indication.jsonDict + dict["indication"] = indication.jsonDict as AnyObject? } - if precondition.count > 0 { dict["precondition"] = precondition.codes.map({$0.jsonDict}) } - if method.count > 0 { dict["method"] = method.codes.map({$0.jsonDict}) } - if product_form.count > 0 { dict["product_form"] = product_form.codes.map({$0.jsonDict}) } + if precondition.count > 0 { dict["precondition"] = precondition.codes.map({$0.jsonDict}) as AnyObject? } + if method.count > 0 { dict["method"] = method.codes.map({$0.jsonDict}) as AnyObject? } + if product_form.count > 0 { dict["product_form"] = product_form.codes.map({$0.jsonDict}) as AnyObject? } //if reaction.count > 0 { dict["reaction"] = reaction.codes.map({$0.jsonDict}) } if let reaction = reaction { - dict["reaction"] = reaction.jsonDict + dict["reaction"] = reaction.jsonDict as AnyObject? } if let severity = severity { - dict["severity"] = severity.jsonDict + dict["severity"] = severity.jsonDict as AnyObject? } - if route.count > 0 { dict["route"] = route.codes.map({$0.jsonDict}) } - if status_of_medication.count > 0 { dict["status_of_medication"] = status_of_medication.codes.map({$0.jsonDict}) } - if type_of_medication.count > 0 { dict["type_of_medication"] = type_of_medication.codes.map({$0.jsonDict}) } - if vehicle.count > 0 { dict["vehicle"] = vehicle.codes.map({$0.jsonDict}) } + if route.count > 0 { dict["route"] = route.codes.map({$0.jsonDict}) as AnyObject? } + if status_of_medication.count > 0 { dict["status_of_medication"] = status_of_medication.codes.map({$0.jsonDict}) as AnyObject? } + if type_of_medication.count > 0 { dict["type_of_medication"] = type_of_medication.codes.map({$0.jsonDict}) as AnyObject? } + if vehicle.count > 0 { dict["vehicle"] = vehicle.codes.map({$0.jsonDict}) as AnyObject? } - if administration_timing.jsonDict.count > 0 { dict["administration_timing"] = administration_timing.jsonDict } - if dose_restriction.jsonDict.count > 0 { dict["dose_restriction"] = dose_restriction.jsonDict } - if dose.jsonDict.count > 0 { dict["dose"] = dose.jsonDict } - if rate.jsonDict.count > 0 { dict["rate"] = rate.jsonDict } + if administration_timing.jsonDict.count > 0 { dict["administration_timing"] = administration_timing.jsonDict as AnyObject? } + if dose_restriction.jsonDict.count > 0 { dict["dose_restriction"] = dose_restriction.jsonDict as AnyObject? } + if dose.jsonDict.count > 0 { dict["dose"] = dose.jsonDict as AnyObject? } + if rate.jsonDict.count > 0 { dict["rate"] = rate.jsonDict as AnyObject? } - if let active_datetime = active_datetime { dict["active_datetime"] = active_datetime } - if let signed_datetime = signed_datetime { dict["signed_datetime"] = signed_datetime } - if let dose_indicator = dose_indicator { dict["dose_indicator"] = dose_indicator } - if let free_text_sig = free_text_sig { dict["free_text_sig"] = free_text_sig } - if let fulfillment_instructions = fulfillment_instructions { dict["fulfillment_instructions"] = fulfillment_instructions } - if let patient_instructions = patient_instructions { dict["patient_instructions"] = patient_instructions } + if let active_datetime = active_datetime { dict["active_datetime"] = active_datetime as AnyObject? } + if let signed_datetime = signed_datetime { dict["signed_datetime"] = signed_datetime as AnyObject? } + if let dose_indicator = dose_indicator { dict["dose_indicator"] = dose_indicator as AnyObject? } + if let free_text_sig = free_text_sig { dict["free_text_sig"] = free_text_sig as AnyObject? } + if let fulfillment_instructions = fulfillment_instructions { dict["fulfillment_instructions"] = fulfillment_instructions as AnyObject? } + if let patient_instructions = patient_instructions { dict["patient_instructions"] = patient_instructions as AnyObject? } return dict } @@ -258,10 +258,10 @@ extension CDAKMedicationRestriction: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if numerator.jsonDict.count > 0 { - dict["numerator"] = numerator.jsonDict + dict["numerator"] = numerator.jsonDict as AnyObject? } if denominator.jsonDict.count > 0 { - dict["denominator"] = denominator.jsonDict + dict["denominator"] = denominator.jsonDict as AnyObject? } return dict @@ -300,9 +300,9 @@ extension CDAKMedicationAdministrationTiming: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] - dict["institution_specified"] = institution_specified + dict["institution_specified"] = institution_specified as AnyObject? if period.jsonDict.count > 0 { - dict["period"] = period.jsonDict + dict["period"] = period.jsonDict as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/order_information.swift b/CDAKit/health-data-standards/lib/models/order_information.swift index 37d6174..21a5645 100644 --- a/CDAKit/health-data-standards/lib/models/order_information.swift +++ b/CDAKit/health-data-standards/lib/models/order_information.swift @@ -12,27 +12,27 @@ import Foundation /** Order information */ -public class CDAKOrderInformation: CDAKEntry { +open class CDAKOrderInformation: CDAKEntry { // MARK: CDA properties ///order number - public var order_number: String? //, as: :order_number, type: String + open var order_number: String? //, as: :order_number, type: String ///number of filles - public var fills: Int? //, type: Integer + open var fills: Int? //, type: Integer ///number of units ordered - public var quantity_ordered = CDAKValueAndUnit() + open var quantity_ordered = CDAKValueAndUnit() ///date/time of order expiration - public var order_expiration_date_time: Double? //, as: :order_expiration_date_time, type: Integer + open var order_expiration_date_time: Double? //, as: :order_expiration_date_time, type: Integer ///date/time of creation of order - public var order_date_time: Double? //, as: :order_date_time, type: Integer + open var order_date_time: Double? //, as: :order_date_time, type: Integer ///ordering provider - public var provider: CDAKProvider? + open var provider: CDAKProvider? // MARK: Health-Data-Standards Functions ///Offset all dates by specified double - override func shift_dates(date_diff: Double) { + override func shift_dates(_ date_diff: Double) { super.shift_dates(date_diff) if let order_date_time = order_date_time { @@ -52,24 +52,24 @@ extension CDAKOrderInformation { var dict = super.jsonDict if let order_number = order_number { - dict["order_number"] = order_number + dict["order_number"] = order_number as AnyObject? } if let fills = fills { - dict["fills"] = fills + dict["fills"] = fills as AnyObject? } if quantity_ordered.jsonDict.count > 0 { - dict["quantity_ordered"] = quantity_ordered.jsonDict + dict["quantity_ordered"] = quantity_ordered.jsonDict as AnyObject? } if let order_expiration_date_time = order_expiration_date_time { - dict["order_expiration_date_time"] = order_expiration_date_time + dict["order_expiration_date_time"] = order_expiration_date_time as AnyObject? } if let order_date_time = order_date_time { - dict["order_date_time"] = order_date_time + dict["order_date_time"] = order_date_time as AnyObject? } if let provider = provider { - dict["provider"] = provider.jsonDict + dict["provider"] = provider.jsonDict as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/organization.swift b/CDAKit/health-data-standards/lib/models/organization.swift index e5e57f9..f02fbc3 100644 --- a/CDAKit/health-data-standards/lib/models/organization.swift +++ b/CDAKit/health-data-standards/lib/models/organization.swift @@ -12,17 +12,17 @@ import Mustache /** Organization */ -public class CDAKOrganization: CDAKJSONInstantiable, CustomStringConvertible, Equatable, Hashable { +open class CDAKOrganization: CDAKJSONInstantiable, CustomStringConvertible, Equatable, Hashable { // MARK: CDA properties ///organization name - public var name: String? + open var name: String? ///OIds etc. for organization - public var ids: [CDAKCDAIdentifier] = [] //not used in original model. Merged from QRDA ORG model + open var ids: [CDAKCDAIdentifier] = [] //not used in original model. Merged from QRDA ORG model ///physical address - public var addresses: [CDAKAddress] = [CDAKAddress]() + open var addresses: [CDAKAddress] = [CDAKAddress]() ///telecoms - public var telecoms: [CDAKTelecom] = [CDAKTelecom]() + open var telecoms: [CDAKTelecom] = [CDAKTelecom]() // MARK: - Initializers @@ -36,7 +36,7 @@ public class CDAKOrganization: CDAKJSONInstantiable, CustomStringConvertible, Eq } ///Do not use - will be removed. Was used in HDS Ruby. - private func initFromEventList(event: [String:Any?]) { + fileprivate func initFromEventList(_ event: [String:Any?]) { for (key, value) in event { CDAKUtility.setProperty(self, property: key, value: value) } @@ -44,7 +44,7 @@ public class CDAKOrganization: CDAKJSONInstantiable, CustomStringConvertible, Eq // MARK: Standard properties ///Debugging description - public var description: String { + open var description: String { return "CDAKOrganization => name: \(name), addresses: \(addresses), telecoms: \(telecoms)" } @@ -104,16 +104,16 @@ extension CDAKOrganization: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if let name = name { - dict["name"] = name + dict["name"] = name as AnyObject? } if ids.count > 0 { - dict["ids"] = ids.map({$0.jsonDict}) + dict["ids"] = ids.map({$0.jsonDict}) as AnyObject? } if telecoms.count > 0 { - dict["telecoms"] = telecoms.map({$0.jsonDict}) + dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject? } if addresses.count > 0 { - dict["addresses"] = addresses.map({$0.jsonDict}) + dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/person.swift b/CDAKit/health-data-standards/lib/models/person.swift index ddc835f..c794583 100644 --- a/CDAKit/health-data-standards/lib/models/person.swift +++ b/CDAKit/health-data-standards/lib/models/person.swift @@ -12,21 +12,21 @@ import Mustache /** Person. Generic person container. Should not use for a provider. */ -public class CDAKPerson: CDAKPersonable, CDAKJSONInstantiable { +open class CDAKPerson: CDAKPersonable, CDAKJSONInstantiable { // MARK: CDA properties ///Prefix (Mrs., MD., etc.) (was Title) - public var prefix: String? + open var prefix: String? ///First / given name - public var given_name: String? + open var given_name: String? ///Family / last name - public var family_name: String? + open var family_name: String? ///Suffix - public var suffix: String? + open var suffix: String? ///addresses - public var addresses: [CDAKAddress] = [CDAKAddress]() + open var addresses: [CDAKAddress] = [CDAKAddress]() ///telecoms - public var telecoms: [CDAKTelecom] = [CDAKTelecom]() + open var telecoms: [CDAKTelecom] = [CDAKTelecom]() // MARK: - Initializers public init(prefix: String? = nil, given_name: String? = nil, family_name: String? = nil, suffix: String? = nil, addresses: [CDAKAddress] = [], telecoms: [CDAKTelecom] = []){ @@ -79,23 +79,23 @@ extension CDAKPerson: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] if let prefix = prefix { - dict["prefix"] = prefix + dict["prefix"] = prefix as AnyObject? } if let given_name = given_name { - dict["given"] = given_name + dict["given"] = given_name as AnyObject? } if let family_name = family_name { - dict["family_name"] = family_name + dict["family_name"] = family_name as AnyObject? } if let suffix = suffix { - dict["suffix"] = suffix + dict["suffix"] = suffix as AnyObject? } if telecoms.count > 0 { - dict["telecoms"] = telecoms.map({$0.jsonDict}) + dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject? } if addresses.count > 0 { - dict["addresses"] = addresses.map({$0.jsonDict}) + dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/physical_quantity_result_value.swift b/CDAKit/health-data-standards/lib/models/physical_quantity_result_value.swift index 335fd48..411d673 100644 --- a/CDAKit/health-data-standards/lib/models/physical_quantity_result_value.swift +++ b/CDAKit/health-data-standards/lib/models/physical_quantity_result_value.swift @@ -15,12 +15,12 @@ import Mustache /** Subclass of CDAKResultValue. Represents a known fixed physical result value (PQ, etc.) */ -public class CDAKPhysicalQuantityResultValue: CDAKResultValue { +open class CDAKPhysicalQuantityResultValue: CDAKResultValue { // MARK: CDA properties ///scalar value like "6" or "true" - public var scalar: String? //no clue what this type should be, so sticking with String for now + open var scalar: String? //no clue what this type should be, so sticking with String for now ///units. Most commonly UCUM units, but there is no restriction - public var units: String? + open var units: String? // MARK: - Initializers public init(scalar: Any?, units: String? = nil) { @@ -39,13 +39,13 @@ public class CDAKPhysicalQuantityResultValue: CDAKResultValue { // MARK: Standard properties ///hash value for comparing objects - override public var hashValue: Int { + override open var hashValue: Int { return "\(scalar)\(units)".hashValue } ///Debugging description - override public var description: String { - return "\(self.dynamicType) => attributes: \(attributes), time: \(time), start_time: \(start_time), end_time: \(end_time), scalar: \(scalar), units: \(units)" + override open var description: String { + return "\(type(of: self)) => attributes: \(attributes), time: \(time), start_time: \(start_time), end_time: \(end_time), scalar: \(scalar), units: \(units)" } @@ -66,7 +66,7 @@ extension CDAKPhysicalQuantityResultValue { ] } - override public var mustacheBox: MustacheBox { + override open var mustacheBox: MustacheBox { return Box(boxedValues) } @@ -79,12 +79,12 @@ extension CDAKPhysicalQuantityResultValue { var dict = super.jsonDict if let scalar = scalar { - dict["scalar"] = scalar + dict["scalar"] = scalar as AnyObject? } if let units = units { - dict["units"] = units + dict["units"] = units as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/procedure.swift b/CDAKit/health-data-standards/lib/models/procedure.swift index 1205e7e..a410558 100644 --- a/CDAKit/health-data-standards/lib/models/procedure.swift +++ b/CDAKit/health-data-standards/lib/models/procedure.swift @@ -12,36 +12,36 @@ import Mustache /** Medical procedure. Commonly used for things like surgical procedures. */ -public class CDAKProcedure: CDAKEntry { +open class CDAKProcedure: CDAKEntry { // MARK: CDA properties ///date/time of first incision. NOT start of case. First incision. - public var incision_time : Double? //, type: Integer, as: :incision_time + open var incision_time : Double? //, type: Integer, as: :incision_time ///ordinality - public var ordinality: CDAKCodedEntries = CDAKCodedEntries() //, type: Hash + open var ordinality: CDAKCodedEntries = CDAKCodedEntries() //, type: Hash ///source - public var source: CDAKCodedEntries = CDAKCodedEntries() //, type: Hash + open var source: CDAKCodedEntries = CDAKCodedEntries() //, type: Hash ///anatomical approach - public var anatomical_approach: CDAKCodedEntries = CDAKCodedEntries() // + open var anatomical_approach: CDAKCodedEntries = CDAKCodedEntries() // ///anatomical target - public var anatomical_target: CDAKCodedEntries = CDAKCodedEntries() // + open var anatomical_target: CDAKCodedEntries = CDAKCodedEntries() // ///method - public var method: CDAKCodedEntries = CDAKCodedEntries() // + open var method: CDAKCodedEntries = CDAKCodedEntries() // ///reaction - public var reaction: CDAKCodedEntries = CDAKCodedEntries() // + open var reaction: CDAKCodedEntries = CDAKCodedEntries() // ///radiation dost - public var radiation_dose: CDAKCodedEntries = CDAKCodedEntries() //this is probably wrong + open var radiation_dose: CDAKCodedEntries = CDAKCodedEntries() //this is probably wrong ///radiation duration. It is currently unclear how this should be represented - public var radiation_duration: CDAKCodedEntries = CDAKCodedEntries() //this is probably wrong + open var radiation_duration: CDAKCodedEntries = CDAKCodedEntries() //this is probably wrong ///facility where procedure occurred - public var facility: CDAKFacility? + open var facility: CDAKFacility? ///provider who was primary actor - public var performer: CDAKProvider? + open var performer: CDAKProvider? // MARK: Health-Data-Standards Functions ///Offset all dates by specified double - override func shift_dates(date_diff: Double) { + override func shift_dates(_ date_diff: Double) { super.shift_dates(date_diff) if let incision_time = incision_time { @@ -81,39 +81,39 @@ extension CDAKProcedure { var dict = super.jsonDict if let incision_time = incision_time { - dict["incision_time"] = incision_time + dict["incision_time"] = incision_time as AnyObject? } if ordinality.count > 0 { - dict["ordinality"] = ordinality.codes.map({$0.jsonDict}) + dict["ordinality"] = ordinality.codes.map({$0.jsonDict}) as AnyObject? } if source.count > 0 { - dict["source"] = source.codes.map({$0.jsonDict}) + dict["source"] = source.codes.map({$0.jsonDict}) as AnyObject? } if anatomical_approach.count > 0 { - dict["anatomical_approach"] = anatomical_approach.codes.map({$0.jsonDict}) + dict["anatomical_approach"] = anatomical_approach.codes.map({$0.jsonDict}) as AnyObject? } if anatomical_target.count > 0 { - dict["anatomical_target"] = anatomical_target.codes.map({$0.jsonDict}) + dict["anatomical_target"] = anatomical_target.codes.map({$0.jsonDict}) as AnyObject? } if method.count > 0 { - dict["method"] = method.codes.map({$0.jsonDict}) + dict["method"] = method.codes.map({$0.jsonDict}) as AnyObject? } if reaction.count > 0 { - dict["reaction"] = reaction.codes.map({$0.jsonDict}) + dict["reaction"] = reaction.codes.map({$0.jsonDict}) as AnyObject? } if radiation_dose.count > 0 { - dict["radiation_dose"] = radiation_dose.codes.map({$0.jsonDict}) + dict["radiation_dose"] = radiation_dose.codes.map({$0.jsonDict}) as AnyObject? } if radiation_duration.count > 0 { - dict["radiation_duration"] = radiation_duration.codes.map({$0.jsonDict}) + dict["radiation_duration"] = radiation_duration.codes.map({$0.jsonDict}) as AnyObject? } if let facility = facility { - dict["facility"] = facility.jsonDict + dict["facility"] = facility.jsonDict as AnyObject? } if let performer = performer { - dict["performer"] = performer.jsonDict + dict["performer"] = performer.jsonDict as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/provider.swift b/CDAKit/health-data-standards/lib/models/provider.swift index 15b1849..642e598 100644 --- a/CDAKit/health-data-standards/lib/models/provider.swift +++ b/CDAKit/health-data-standards/lib/models/provider.swift @@ -13,7 +13,7 @@ import Mustache Represents a care provider */ -public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equatable, CustomStringConvertible { +open class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equatable, CustomStringConvertible { static let NPI_OID = "2.16.840.1.113883.4.6" static let NPI_OID_C83 = "2.16.840.1.113883.3.72.5.2" @@ -23,25 +23,25 @@ public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equat // MARK: CDA properties ///Prefix (was: Title) - public var prefix: String? + open var prefix: String? ///Suffix - public var suffix: String? + open var suffix: String? ///Given / First name - public var given_name: String? + open var given_name: String? ///Family / Last name - public var family_name: String? + open var family_name: String? ///addresses - public var addresses: [CDAKAddress] = [CDAKAddress]() + open var addresses: [CDAKAddress] = [CDAKAddress]() ///telecoms - public var telecoms: [CDAKTelecom] = [CDAKTelecom]() + open var telecoms: [CDAKTelecom] = [CDAKTelecom]() ///provider specialty - public var specialty: String? + open var specialty: String? ///provider phone - public var phone: String? + open var phone: String? ///provider organization - public var organization: CDAKOrganization? + open var organization: CDAKOrganization? ///CDA identifiers. Contains NPI if supplied. - public var cda_identifiers: [CDAKCDAIdentifier] = [CDAKCDAIdentifier]() + open var cda_identifiers: [CDAKCDAIdentifier] = [CDAKCDAIdentifier]() /** @@ -73,13 +73,13 @@ public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equat ``` */ - public var code: CDAKCodedEntry? + open var code: CDAKCodedEntry? // Update the CDA identifier references for NPI // NOTE there are actually two ways to refer to NPI (two OIDs) // please refer to the provider importer and tests for examples where this occurs ///Allows you to quickly set or retrieve the NPI without specifying OID - public var npi : String? { + open var npi : String? { get { let cda_id_npi = cda_identifiers.filter({ $0.root == CDAKProvider.NPI_OID }).first return cda_id_npi != nil ? cda_id_npi?.extension_id : nil @@ -93,7 +93,7 @@ public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equat } } ///Allows you to quickly set or retrive TIN (Tax ID Number) without specifying OID - public var tin: String? { + open var tin: String? { get { let cda_id_tin = cda_identifiers.filter({ $0.root == CDAKProvider.TAX_ID_OID }).first return cda_id_tin != nil ? cda_id_tin?.extension_id : nil @@ -122,7 +122,7 @@ public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equat //scope :by_npi, ->(an_npi){ where("cda_identifiers.root" => NPI_OID, "cda_identifiers.extension" => an_npi)} ///searches for a provider by NPI. Queries the external provider collection. - class func by_npi(an_npi: String?) -> CDAKProvider? { + class func by_npi(_ an_npi: String?) -> CDAKProvider? { for prov in CDAKGlobals.sharedInstance.CDAKProviders { for cda in prov.cda_identifiers { if (cda.root == CDAKProvider.NPI_OID) && cda.extension_id == an_npi { @@ -147,7 +147,7 @@ public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equat [NPI Check Digit](https://www.cms.gov/NationalProvIdentStand/Downloads/NPIcheckdigit.pdf) */ - public class func valid_npi(npi: String?) -> Bool { + open class func valid_npi(_ npi: String?) -> Bool { guard var npi = npi else { return false } @@ -171,15 +171,18 @@ public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equat //NOTE: the original Ruby code was [0,14] - start at 0 with length of 14 - so end at _13_ // the second Ruby was [14] - so just go to position 14 // return luhn_checksum(npi[0,14]) == npi[14] - return luhn_checksum(npi[0...13]) == npi[14...14] + //return luhn_checksum(npi[0...13]) == npi[14...14] + + let result = luhn_checksum(npi.substring(with: 0..<14)) == npi.substring(with: 14..<15) + return luhn_checksum(npi.substring(with: 0..<14)) == npi.substring(with: 14..<15) } - class func luhn_checksum(num: String) -> String { + class func luhn_checksum(_ num: String) -> String { let double: [Character:Int] = ["0":0, "1":2, "2":4, "3":6, "4":8, "5":1, "6":3, "7":5, "8":7, "9":9] var sum = 0 - let reversed_num = String(num.characters.reverse()) + let reversed_num = String(num.characters.reversed()) //num.split("").each_with_index do |char, i| - for (i, char) in reversed_num.characters .enumerate() { + for (i, char) in reversed_num.characters .enumerated() { if (i%2) == 0 { sum += double[char]! } else { @@ -201,10 +204,10 @@ public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equat NOTE: In Swift 2.1 we cannot provide default arguments for closures, so if you use the resolve_provider closure you'll need to send in nil for patient if there isn't one */ - class func resolve_provider(provider_hash: [String:Any], patient: CDAKPerson? = nil, resolve_function:((provider_hash: [String:Any], patient: CDAKPerson? ) -> CDAKProvider?)? = nil ) -> CDAKProvider? { + class func resolve_provider(_ provider_hash: [String:Any], patient: CDAKPerson? = nil, resolve_function:((_ provider_hash: [String:Any], _ patient: CDAKPerson? ) -> CDAKProvider?)? = nil ) -> CDAKProvider? { //Provider.where(:npi => nil).first if let resolve_function = resolve_function { - let p = resolve_function(provider_hash: provider_hash, patient: patient ?? nil) + let p = resolve_function(provider_hash, patient ?? nil) return p } else { //let p = CDAKGlobals.sharedInstance.CDAKProviders.filter({ $0.npi == nil }).first @@ -219,7 +222,7 @@ public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equat // MARK: Standard properties ///Debugging description - public var description: String { + open var description: String { return "Provider => prefix: \(prefix), given_name: \(given_name), family_name: \(family_name), suffix: \(suffix), npi: \(npi), specialty: \(specialty), phone: \(phone), organization: \(organization), cda_identifiers: \(cda_identifiers), addresses: \(addresses), telecoms: \(telecoms), code: \(code)" } @@ -228,15 +231,15 @@ public class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equat extension CDAKProvider { ///Removed a given provider from the global collection - class func removeProvider(provider: CDAKProvider) { + class func removeProvider(_ provider: CDAKProvider) { var matching_idx: Int? - for (i, p) in CDAKGlobals.sharedInstance.CDAKProviders.enumerate() { + for (i, p) in CDAKGlobals.sharedInstance.CDAKProviders.enumerated() { if p == provider { matching_idx = i } } if let matching_idx = matching_idx { - CDAKGlobals.sharedInstance.CDAKProviders.removeAtIndex(matching_idx) + CDAKGlobals.sharedInstance.CDAKProviders.remove(at: matching_idx) } } } @@ -311,42 +314,42 @@ extension CDAKProvider: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if let prefix = prefix { - dict["prefix"] = prefix + dict["prefix"] = prefix as AnyObject? } if let given_name = given_name { - dict["given_name"] = given_name + dict["given_name"] = given_name as AnyObject? } if let family_name = family_name { - dict["family_name"] = family_name + dict["family_name"] = family_name as AnyObject? } if let suffix = suffix { - dict["suffix"] = suffix + dict["suffix"] = suffix as AnyObject? } if telecoms.count > 0 { - dict["telecoms"] = telecoms.map({$0.jsonDict}) + dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject? } if addresses.count > 0 { - dict["addresses"] = addresses.map({$0.jsonDict}) + dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } if let specialty = specialty { - dict["specialty"] = specialty + dict["specialty"] = specialty as AnyObject? } if let phone = phone { - dict["phone"] = phone + dict["phone"] = phone as AnyObject? } if let organization = organization { - dict["organization"] = organization.jsonDict + dict["organization"] = organization.jsonDict as AnyObject? } if cda_identifiers.count > 0 { - dict["cda_identifiers"] = cda_identifiers.map({$0.jsonDict}) + dict["cda_identifiers"] = cda_identifiers.map({$0.jsonDict}) as AnyObject? } if let code = code { - dict["code"] = code.jsonDict + dict["code"] = code.jsonDict as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/provider_performance.swift b/CDAKit/health-data-standards/lib/models/provider_performance.swift index aa03a07..1e93770 100644 --- a/CDAKit/health-data-standards/lib/models/provider_performance.swift +++ b/CDAKit/health-data-standards/lib/models/provider_performance.swift @@ -14,17 +14,17 @@ import Mustache Supplies a relationship between a patient and a provider for a particulary start/end date and function. */ -public class CDAKProviderPerformance: CDAKEntry { +open class CDAKProviderPerformance: CDAKEntry { // MARK: CDA properties ///start date for period - public var start_date: Double? + open var start_date: Double? ///end date for period - public var end_date: Double? + open var end_date: Double? ///provider - public var provider: CDAKProvider? + open var provider: CDAKProvider? /** @@ -75,11 +75,11 @@ public class CDAKProviderPerformance: CDAKEntry { * TASST (third assistant) */ - public var functionCode: CDAKCodedEntry? + open var functionCode: CDAKCodedEntry? // MARK: Health-Data-Standards Functions ///Offset all dates by specified double - override func shift_dates(date_diff: Double) { + override func shift_dates(_ date_diff: Double) { super.shift_dates(date_diff) if let start_date = start_date { @@ -92,8 +92,8 @@ public class CDAKProviderPerformance: CDAKEntry { // MARK: Standard properties ///Debugging description - override public var description: String { - return "\(self.dynamicType) => start_date:\(start_date), end_date:\(end_date), functionCode:\(functionCode), provider:\(provider)" + override open var description: String { + return "\(type(of: self)) => start_date:\(start_date), end_date:\(end_date), functionCode:\(functionCode), provider:\(provider)" } } @@ -119,18 +119,18 @@ extension CDAKProviderPerformance { var dict = super.jsonDict if let start_date = start_date { - dict["start_date"] = start_date + dict["start_date"] = start_date as AnyObject? } if let end_date = end_date { - dict["end_date"] = end_date + dict["end_date"] = end_date as AnyObject? } if let provider = provider { - dict["provider"] = provider.jsonDict + dict["provider"] = provider.jsonDict as AnyObject? } if let functionCode = functionCode { - dict["functionCode"] = functionCode.jsonDict + dict["functionCode"] = functionCode.jsonDict as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/provider_preference.swift b/CDAKit/health-data-standards/lib/models/provider_preference.swift index da135a5..919c6de 100644 --- a/CDAKit/health-data-standards/lib/models/provider_preference.swift +++ b/CDAKit/health-data-standards/lib/models/provider_preference.swift @@ -9,6 +9,6 @@ import Foundation ///Empty -public class CDAKProviderPreference { +open class CDAKProviderPreference { //nothing here... -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDAAuthor.swift b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDAAuthor.swift index bf49fc3..d5882d7 100644 --- a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDAAuthor.swift +++ b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDAAuthor.swift @@ -9,14 +9,14 @@ import Foundation import Mustache -public class CDAKQRDAAuthor { - public var time = NSDate() - public var ids: [CDAKCDAIdentifier] = [] - public var addresses: [CDAKAddress] = [] - public var telecoms: [CDAKTelecom] = [] - public var person: CDAKPerson? - public var device: CDAKQRDADevice? - public var organization: CDAKOrganization? +open class CDAKQRDAAuthor { + open var time = Date() + open var ids: [CDAKCDAIdentifier] = [] + open var addresses: [CDAKAddress] = [] + open var telecoms: [CDAKTelecom] = [] + open var person: CDAKPerson? + open var device: CDAKQRDADevice? + open var organization: CDAKOrganization? } extension CDAKQRDAAuthor: CustomStringConvertible { @@ -46,24 +46,24 @@ extension CDAKQRDAAuthor: MustacheBoxable { extension CDAKQRDAAuthor: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] - dict["time"] = time.description + dict["time"] = time.description as AnyObject? if ids.count > 0 { - dict["ids"] = ids.map({$0.jsonDict}) + dict["ids"] = ids.map({$0.jsonDict}) as AnyObject? } if addresses.count > 0 { - dict["addresses"] = addresses.map({$0.jsonDict}) + dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } if telecoms.count > 0 { - dict["telecoms"] = telecoms.map({$0.jsonDict}) + dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject? } if let person = person { - dict["person"] = person.jsonDict + dict["person"] = person.jsonDict as AnyObject? } if let device = device { - dict["device"] = device.jsonDict + dict["device"] = device.jsonDict as AnyObject? } if let organization = organization { - dict["organization"] = organization.jsonDict + dict["organization"] = organization.jsonDict as AnyObject? } return dict } diff --git a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDACustodian.swift b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDACustodian.swift index 2842b9c..d399218 100644 --- a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDACustodian.swift +++ b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDACustodian.swift @@ -9,10 +9,10 @@ import Foundation import Mustache -public class CDAKQRDACustodian { - public var ids: [CDAKCDAIdentifier] = [] - public var person: CDAKPerson? //I see no cases where this is used in CDA - public var organization: CDAKOrganization? +open class CDAKQRDACustodian { + open var ids: [CDAKCDAIdentifier] = [] + open var person: CDAKPerson? //I see no cases where this is used in CDA + open var organization: CDAKOrganization? } extension CDAKQRDACustodian: CustomStringConvertible { @@ -39,14 +39,14 @@ extension CDAKQRDACustodian: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] if ids.count > 0 { - dict["ids"] = ids.map({$0.jsonDict}) + dict["ids"] = ids.map({$0.jsonDict}) as AnyObject? } if let person = person { - dict["person"] = person.jsonDict + dict["person"] = person.jsonDict as AnyObject? } if let organization = organization { - dict["organization"] = organization.jsonDict + dict["organization"] = organization.jsonDict as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDADevice.swift b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDADevice.swift index 020204f..1407384 100644 --- a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDADevice.swift +++ b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDADevice.swift @@ -9,9 +9,9 @@ import Foundation import Mustache -public class CDAKQRDADevice { - public var name: String? - public var model: String? +open class CDAKQRDADevice { + open var name: String? + open var model: String? } extension CDAKQRDADevice: CustomStringConvertible { @@ -38,11 +38,11 @@ extension CDAKQRDADevice: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] if let name = name { - dict["name"] = name + dict["name"] = name as AnyObject? } if let model = model { - dict["model"] = model + dict["model"] = model as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDAHeader.swift b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDAHeader.swift index 451cf86..905d4e6 100644 --- a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDAHeader.swift +++ b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDAHeader.swift @@ -9,18 +9,18 @@ import Foundation import Mustache -public class CDAKQRDAHeader { - public var identifier: CDAKCDAIdentifier? - public var authors: [CDAKQRDAAuthor] = [] - public var custodian: CDAKQRDACustodian? - public var legal_authenticator: CDAKQRDALegalAuthenticator? - public var performers: [CDAKProvider] = [] +open class CDAKQRDAHeader { + open var identifier: CDAKCDAIdentifier? + open var authors: [CDAKQRDAAuthor] = [] + open var custodian: CDAKQRDACustodian? + open var legal_authenticator: CDAKQRDALegalAuthenticator? + open var performers: [CDAKProvider] = [] //FIX_ME: For now, ignore this. This is probably coming from the record that contains the header and the performers (providers) related to this record. I'm not sure how they do this in Mongo, but I can't find any direct cases of this being explicilty populated in the header. This is really only used for QRDA3 right now, so let's just defer doing this. - public var time = NSDate() + open var time = Date() //NOTE: not originally in QRDA header. Adding because we want to be able to vary this - public var confidentiality: CDAKConfidentialityCodes = .Normal - public var title: String? + open var confidentiality: CDAKConfidentialityCodes = .Normal + open var title: String? } extension CDAKQRDAHeader: CustomStringConvertible { @@ -70,23 +70,23 @@ extension CDAKQRDAHeader: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] if let identifier = identifier { - dict["identifier"] = identifier.jsonDict + dict["identifier"] = identifier.jsonDict as AnyObject? } if authors.count > 0 { - dict["authors"] = authors.map({$0.jsonDict}) + dict["authors"] = authors.map({$0.jsonDict}) as AnyObject? } if let custodian = custodian { - dict["custodian"] = custodian.jsonDict + dict["custodian"] = custodian.jsonDict as AnyObject? } if let legal_authenticator = legal_authenticator { - dict["legal_authenticator"] = legal_authenticator.jsonDict + dict["legal_authenticator"] = legal_authenticator.jsonDict as AnyObject? } if performers.count > 0 { - dict["performers"] = performers + dict["performers"] = performers as AnyObject? } - dict["time"] = time.description + dict["time"] = time.description as AnyObject? if let title = title { - dict["title"] = title + dict["title"] = title as AnyObject? } return dict } diff --git a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDALegalAuthenticator.swift b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDALegalAuthenticator.swift index 5e448be..9b0b4b0 100644 --- a/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDALegalAuthenticator.swift +++ b/CDAKit/health-data-standards/lib/models/qrda/CDAKQRDALegalAuthenticator.swift @@ -9,13 +9,13 @@ import Foundation import Mustache -public class CDAKQRDALegalAuthenticator { - public var time = NSDate() - public var telecoms: [CDAKTelecom] = [] - public var ids: [CDAKCDAIdentifier] = [] - public var addresses: [CDAKAddress] = [] - public var person: CDAKPerson? - public var organization: CDAKOrganization? +open class CDAKQRDALegalAuthenticator { + open var time = Date() + open var telecoms: [CDAKTelecom] = [] + open var ids: [CDAKCDAIdentifier] = [] + open var addresses: [CDAKAddress] = [] + open var person: CDAKPerson? + open var organization: CDAKOrganization? } extension CDAKQRDALegalAuthenticator: CustomStringConvertible { @@ -45,25 +45,25 @@ extension CDAKQRDALegalAuthenticator: MustacheBoxable { extension CDAKQRDALegalAuthenticator: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] - dict["time"] = time.description + dict["time"] = time.description as AnyObject? if let person = person { - dict["person"] = person.jsonDict + dict["person"] = person.jsonDict as AnyObject? } if ids.count > 0 { - dict["ids"] = ids.map({$0.jsonDict}) + dict["ids"] = ids.map({$0.jsonDict}) as AnyObject? } if telecoms.count > 0 { - dict["telecoms"] = telecoms.map({$0.jsonDict}) + dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject? } if addresses.count > 0 { - dict["addresses"] = addresses.map({$0.jsonDict}) + dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } if let person = person { - dict["person"] = person.jsonDict + dict["person"] = person.jsonDict as AnyObject? } if let organization = organization { - dict["organization"] = organization.jsonDict + dict["organization"] = organization.jsonDict as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/reason.swift b/CDAKit/health-data-standards/lib/models/reason.swift index 8b87d51..c19d433 100644 --- a/CDAKit/health-data-standards/lib/models/reason.swift +++ b/CDAKit/health-data-standards/lib/models/reason.swift @@ -16,10 +16,10 @@ import Mustache /** Reason */ -public class CDAKReason: CDAKEntry { +open class CDAKReason: CDAKEntry { // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return "CDAKReason => description: \(item_description), codes: \(codes)" } diff --git a/CDAKit/health-data-standards/lib/models/record.swift b/CDAKit/health-data-standards/lib/models/record.swift index 4274d4a..dfcb49a 100644 --- a/CDAKit/health-data-standards/lib/models/record.swift +++ b/CDAKit/health-data-standards/lib/models/record.swift @@ -8,6 +8,35 @@ import Foundation import Mustache +fileprivate func < (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } +} + +fileprivate func <= (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l <= r + default: + return !(rhs < lhs) + } +} + +fileprivate func >= (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l >= r + default: + return !(lhs < rhs) + } +} + public struct code_and_name { var code: String @@ -49,30 +78,30 @@ Primary container for all patient data that is to be represented with CDA ``` */ -public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { +open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { // MARK: CDA properties ///patient prefix (was title) - public var prefix: String? + open var prefix: String? ///patient first / given name - public var first: String? + open var first: String? ///patient last / family name - public var last: String? + open var last: String? ///patient suffix - public var suffix: String? + open var suffix: String? ///patient gender. Please consider using an HL7 Administrative Gender - public var gender: String? + open var gender: String? ///birthdate (using time since 1970) - public var birthdate: Double? + open var birthdate: Double? ///date of death (using time since 1970) - public var deathdate: Double? + open var deathdate: Double? ///religious affiliation(s) - public var religious_affiliation: CDAKCodedEntries = CDAKCodedEntries() + open var religious_affiliation: CDAKCodedEntries = CDAKCodedEntries() ///effective time for record (not date created - date last valid) - public var effective_time: Double? + open var effective_time: Double? ///global unique identifier for record. Defaulted. - public var _id: String = NSUUID().UUIDString + open var _id: String = UUID().uuidString /** When creating this record, you may wish to supply a custom header (CDAKQRDAHeader) or during CDA XML generation a default boilerplate header will be applied @@ -81,7 +110,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { Optionally, you can disable the global header import by toggling `disableGlobalHeader` */ - public var header: CDAKQRDAHeader? { + open var header: CDAKQRDAHeader? { get { if let local_header = _header { return local_header @@ -95,10 +124,10 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { _header = newValue } } - private var _header: CDAKQRDAHeader? + fileprivate var _header: CDAKQRDAHeader? ///Allows you to toggle whether the global header is completely disabled for this record - public var disableGlobalHeader = false + open var disableGlobalHeader = false // FIX_ME: - apparently the JSON has "pregnancies" as its own item // that's not on the dx or problem list (which makes sense - sort of) @@ -106,36 +135,36 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { // figure out where this is coming from and how to handle // for now, making it an "entry" ///any known patient pregnancies - public var pregnancies: [CDAKEntry] = [] + open var pregnancies: [CDAKEntry] = [] // CHANGED: - race / ethnicity really should be a multi-value fields. Original did NOT do this // MU2 allows for multiple ///patient race (coded) - public var race: CDAKCodedEntries = CDAKCodedEntries() + open var race: CDAKCodedEntries = CDAKCodedEntries() ///patient ethnicities (coded) - public var ethnicity: CDAKCodedEntries = CDAKCodedEntries() + open var ethnicity: CDAKCodedEntries = CDAKCodedEntries() ///patient languages (coded) - public var languages: [CDAKCodedEntries] = [] //Array, default: [] + open var languages: [CDAKCodedEntries] = [] //Array, default: [] ///patient martial status (coded) - public var marital_status: CDAKCodedEntries = CDAKCodedEntries() + open var marital_status: CDAKCodedEntries = CDAKCodedEntries() ///patient medical record number - public var medical_record_number: String? + open var medical_record_number: String? ///patient medical record assigner - public var medical_record_assigner: String? + open var medical_record_assigner: String? ///is patient expired? (deceased) - public var expired: Bool? + open var expired: Bool? //NOT IN MODEL ///is this patient a clinical trial participant? Please refer to CMS guidance on implications - public var clinicalTrialParticipant: Bool? //NOT in model, but in Mongo JSON (probably for QRDA) + open var clinicalTrialParticipant: Bool? //NOT in model, but in Mongo JSON (probably for QRDA) ///name of record custodian? - public var custodian: String? //NOT in model, but in Mongo JSON (probably for QRDA) + open var custodian: String? //NOT in model, but in Mongo JSON (probably for QRDA) ///any patient identifiers. This may include collections of MRNs if you use multiple EMRs, etc. Could conceivably include identifiers like SSN - public var identifiers: [CDAKCDAIdentifier] = [] // NOT in the orignal model, but we want to have these on hand + open var identifiers: [CDAKCDAIdentifier] = [] // NOT in the orignal model, but we want to have these on hand - private var _addresses = [CDAKAddress]() //, as: :locatable + fileprivate var _addresses = [CDAKAddress]() //, as: :locatable ///patient addresses - public var addresses: [CDAKAddress] { + open var addresses: [CDAKAddress] { get {return _addresses} set { // for c in newValue { @@ -145,9 +174,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _telecoms = [CDAKTelecom]() //, as: :contactable + fileprivate var _telecoms = [CDAKTelecom]() //, as: :contactable ///patient telecoms - public var telecoms: [CDAKTelecom] { + open var telecoms: [CDAKTelecom] { get {return _telecoms} set { // for c in newValue { @@ -159,19 +188,19 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { ///Determines whether patient is currently over the age of 18 - public var over_18: Bool { + open var over_18: Bool { //Time.at(birthdate) < Time.now.years_ago(18) guard let birthdate = birthdate else { return false } //http://stackoverflow.com/questions/24723431/swift-days-between-two-nsdates - let start_date = NSDate(timeIntervalSince1970: NSTimeInterval(birthdate)) - let end_date = NSDate() //now + let start_date = Date(timeIntervalSince1970: TimeInterval(birthdate)) + let end_date = Date() //now - let cal = NSCalendar.currentCalendar() - let year_unit : NSCalendarUnit = NSCalendarUnit.Year - let components = cal.components(year_unit, fromDate: start_date, toDate: end_date, options: []) + let cal = Calendar.current + let year_unit : NSCalendar.Unit = NSCalendar.Unit.year + let components = (cal as NSCalendar).components(year_unit, from: start_date, to: end_date, options: []) if components.year >= 18 { return true @@ -185,9 +214,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { // When we create an entry and append it to the entry array(s), we create a reference back to this Record // MARK: - Collections of child Entries for CDA Sections - private var _allergies = [CDAKAllergy]() + fileprivate var _allergies = [CDAKAllergy]() ///Allergies collection - public var allergies: [CDAKAllergy] { + open var allergies: [CDAKAllergy] { get {return _allergies} set { for c in newValue { @@ -197,9 +226,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _care_goals = [CDAKEntry]() + fileprivate var _care_goals = [CDAKEntry]() ///This can be any number of different entry types - public var care_goals: [CDAKEntry] { + open var care_goals: [CDAKEntry] { get {return _care_goals} set { for c in newValue { @@ -209,9 +238,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _conditions = [CDAKCondition]() + fileprivate var _conditions = [CDAKCondition]() ///conditions collection - public var conditions: [CDAKCondition] { + open var conditions: [CDAKCondition] { get {return _conditions} set { for c in newValue { @@ -221,9 +250,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _encounters = [CDAKEncounter]() + fileprivate var _encounters = [CDAKEncounter]() ///encounters collection - public var encounters: [CDAKEncounter] { + open var encounters: [CDAKEncounter] { get {return _encounters} set { for c in newValue { @@ -233,9 +262,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _communications = [CDAKCommunication]() + fileprivate var _communications = [CDAKCommunication]() ///communications collection - public var communications: [CDAKCommunication] { + open var communications: [CDAKCommunication] { get {return _communications} set { for c in newValue { @@ -245,9 +274,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _family_history = [CDAKFamilyHistory]() + fileprivate var _family_history = [CDAKFamilyHistory]() ///family history collection - public var family_history: [CDAKFamilyHistory] { + open var family_history: [CDAKFamilyHistory] { get {return _family_history} set { for c in newValue { @@ -257,9 +286,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _immunizations = [CDAKImmunization]() + fileprivate var _immunizations = [CDAKImmunization]() ///immunizations collection - public var immunizations: [CDAKImmunization] { + open var immunizations: [CDAKImmunization] { get {return _immunizations} set { for c in newValue { @@ -269,9 +298,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _medical_equipment = [CDAKMedicalEquipment]() + fileprivate var _medical_equipment = [CDAKMedicalEquipment]() ///medical equipment collection - public var medical_equipment: [CDAKMedicalEquipment] { + open var medical_equipment: [CDAKMedicalEquipment] { get {return _medical_equipment} set { for c in newValue { @@ -282,9 +311,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } - private var _medications = [CDAKMedication]() + fileprivate var _medications = [CDAKMedication]() ///medications collection - public var medications: [CDAKMedication] { + open var medications: [CDAKMedication] { get {return _medications} set { for c in newValue { @@ -294,9 +323,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _procedures = [CDAKProcedure]() + fileprivate var _procedures = [CDAKProcedure]() ///procedures collection - public var procedures: [CDAKProcedure] { + open var procedures: [CDAKProcedure] { get {return _procedures} set { for c in newValue { @@ -306,9 +335,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _results = [CDAKLabResult]()//, class_name: "CDAKLabResult" + fileprivate var _results = [CDAKLabResult]()//, class_name: "CDAKLabResult" ///lab results collection - public var results: [CDAKLabResult] { + open var results: [CDAKLabResult] { get {return _results} set { for c in newValue { @@ -318,9 +347,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _socialhistories = [CDAKSocialHistory]() //, class_name: "CDAKEntry" + fileprivate var _socialhistories = [CDAKSocialHistory]() //, class_name: "CDAKEntry" ///social histories collection - public var social_history: [CDAKSocialHistory] { + open var social_history: [CDAKSocialHistory] { get { return socialhistories } set { socialhistories = newValue } } @@ -334,9 +363,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _vital_signs = [CDAKVitalSign]() + fileprivate var _vital_signs = [CDAKVitalSign]() ///vital signs collection - public var vital_signs: [CDAKVitalSign] { + open var vital_signs: [CDAKVitalSign] { get {return _vital_signs} set { for c in newValue { @@ -346,9 +375,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _support = [CDAKSupport]() + fileprivate var _support = [CDAKSupport]() ///support collection - public var support: [CDAKSupport] { + open var support: [CDAKSupport] { get {return _support} set { for c in newValue { @@ -358,9 +387,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _advance_directives = [CDAKEntry]() //, class_name: "CDAKEntry" + fileprivate var _advance_directives = [CDAKEntry]() //, class_name: "CDAKEntry" ///advance directives collection - public var advance_directives: [CDAKEntry] { + open var advance_directives: [CDAKEntry] { get {return _advance_directives} set { for c in newValue { @@ -370,9 +399,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _insurance_providers = [CDAKInsuranceProvider]() + fileprivate var _insurance_providers = [CDAKInsuranceProvider]() ///insurance providers collection - public var insurance_providers: [CDAKInsuranceProvider] { + open var insurance_providers: [CDAKInsuranceProvider] { get {return _insurance_providers} set { for c in newValue { @@ -382,9 +411,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - private var _functional_statuses = [CDAKFunctionalStatus]() + fileprivate var _functional_statuses = [CDAKFunctionalStatus]() ///functional status collection - public var functional_statuses: [CDAKFunctionalStatus] { + open var functional_statuses: [CDAKFunctionalStatus] { get {return _functional_statuses} set { for c in newValue { @@ -395,12 +424,12 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } //FIX_ME: - I think "provider_performances" shoud be handled differently here - private var _provider_performances = [CDAKProviderPerformance]() + fileprivate var _provider_performances = [CDAKProviderPerformance]() /** provider performances collection This is really only relevant for QRDA III */ - public var provider_performances: [CDAKProviderPerformance] { + open var provider_performances: [CDAKProviderPerformance] { get {return _provider_performances} set { for c in newValue { @@ -414,12 +443,12 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { //MARK: Legacy Ruby ///list of section identifiers. Legacy Ruby - private var Sections = ["allergies", "care_goals", "conditions", "encounters", "immunizations", "medical_equipment", + fileprivate var Sections = ["allergies", "care_goals", "conditions", "encounters", "immunizations", "medical_equipment", "medications", "procedures", "results", "communications", "family_history", "social_history", "vital_signs", "support", "advance_directives", "insurance_providers", "functional_statuses"] ///Legacy Ruby. Search for record(s) by provider. - internal class func by_provider(provider: CDAKProvider, effective_date: Double?) -> [CDAKRecord] { + internal class func by_provider(_ provider: CDAKProvider, effective_date: Double?) -> [CDAKRecord] { // FIX_ME: this is a mess var records = [CDAKRecord]() if let effective_date = effective_date { @@ -448,7 +477,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { //scope :by_patient_id, ->(id) { where(:medical_record_number => id) } ///Legacy Ruby. Searches for a patient record by patient MRN - internal class func by_patient_id(id: String) -> [CDAKRecord] { + internal class func by_patient_id(_ id: String) -> [CDAKRecord] { //FIX_ME: Should this return just one record? var records = [CDAKRecord]() for record in CDAKGlobals.sharedInstance.CDAKRecords { @@ -460,7 +489,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } ///Legacy Ruby. Determines if a record exists already in the record collection - internal class func update_or_create(data: CDAKRecord) -> CDAKRecord { + internal class func update_or_create(_ data: CDAKRecord) -> CDAKRecord { //existing = CDAKRecord.where(medical_record_number: data.medical_record_number).first var existing: CDAKRecord? for record in CDAKGlobals.sharedInstance.CDAKRecords { @@ -486,7 +515,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { ///returns a specific set of patient entry records based on the supplied section name (if found) - private func getSection(section: String) -> [CDAKEntry] { + fileprivate func getSection(_ section: String) -> [CDAKEntry] { //FIX_ME: move this into the CDAK helper stuff switch section { case "allergies" : return allergies @@ -511,7 +540,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } ///based on the supplied section name (if found), replaces entries with supplied collection - private func setSection(section: String, entries: [CDAKEntry]) { + fileprivate func setSection(_ section: String, entries: [CDAKEntry]) { switch section { case "allergies" : allergies = (entries as! [CDAKAllergy]) case "care_goals" : care_goals = entries @@ -535,7 +564,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } ///For a given OID, searches all entries and returns entries with matching OID - internal func entries_for_oid(oid: String) -> [CDAKEntry] { + internal func entries_for_oid(_ oid: String) -> [CDAKEntry] { //OK, so this appears to be sort of reflecting on the Ruby attributes by "section" // EX: section string "allergies" -> looks at object property "allergies" // I don't want to start doing wonky things to work around reflection challenges, so I'm just going to @@ -545,7 +574,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { for section in Sections { let entries = getSection(section) - matching_entries_by_section.appendContentsOf(entries.filter({entry in entry.oid == oid})) + matching_entries_by_section.append(contentsOf: entries.filter({entry in entry.oid == oid})) } @@ -558,7 +587,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { var all_entries = [CDAKEntry]() for section in Sections { let entries = getSection(section) - all_entries.appendContentsOf(entries) + all_entries.append(contentsOf: entries) } return all_entries } @@ -570,7 +599,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { Warning: Marked as mutating / "dangerous" in Ruby */ - internal func dedup_section_ignoring_content(section: String) { + internal func dedup_section_ignoring_content(_ section: String) { // http://stackoverflow.com/questions/612189/why-are-exclamation-marks-used-in-ruby-methods // In general, methods that end in ! indicate that the method will modify the object it's called on. Ruby calls these "dangerous methods" because they change state that someone else might have a reference to. @@ -613,7 +642,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { Attempts to determine if there are duplicate entries in the Record and removes any extras. */ - internal func dedup_section_merging_codes_and_values(section: String) { + internal func dedup_section_merging_codes_and_values(_ section: String) { var unique_entries = [String:CDAKEntry]() let entries = getSection(section) @@ -627,7 +656,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { // "new" is based on the entry identifier if unique_entries[entry.identifier_as_string] != nil { unique_entries[entry.identifier_as_string]!.codes = mergeCodes(unique_entries[entry.identifier_as_string]!.codes, ar2: entry.codes) - unique_entries[entry.identifier_as_string]?.values.appendContentsOf(entry.values) + unique_entries[entry.identifier_as_string]?.values.append(contentsOf: entry.values) } else { unique_entries[entry.identifier_as_string] = entry } @@ -637,14 +666,15 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } ///DO NOT USE. Alternate method exists in Coded Entries. Merges codes between two sets of coded entries - private func mergeCodes(var ar1: CDAKCodedEntries, ar2: CDAKCodedEntries) -> CDAKCodedEntries { + private func mergeCodes(_ ar1: CDAKCodedEntries, ar2: CDAKCodedEntries) -> CDAKCodedEntries { + var ar1 = ar1 for (_, CDAKCodedEntry) in ar2 { ar1.addCodes(CDAKCodedEntry) } return ar1 } - internal func dedup_section(section: String) { + internal func dedup_section(_ section: String) { if ["encounters", "procedures", "results"].contains(section) { dedup_section_merging_codes_and_values(section) } else { @@ -660,7 +690,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { // MARK: Health-Data-Standards Functions ///Offset all dates by specified double - func shift_dates(date_diff: Double) { + func shift_dates(_ date_diff: Double) { if let birthdate = birthdate { self.birthdate = birthdate + date_diff @@ -673,7 +703,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } for sec in Sections { if let property_name = self.propertyNames().filter({$0 == sec}).first { - if let entries = self.valueForKey(property_name) as? [CDAKEntry] { + if let entries = self.value(forKey: property_name) as? [CDAKEntry] { for entry in entries { entry.shift_dates(date_diff) } @@ -683,7 +713,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } - private class func provider_queries(provider_id: String, effective_date: Double) -> CDAKProvider? { + fileprivate class func provider_queries(_ provider_id: String, effective_date: Double) -> CDAKProvider? { //FIX_ME: - review implementation for accuracy //Making the (probably bad) assumption these return a single value - provider_id assumed to be unique // see warning about NPI vs. provider_id on provider_query @@ -700,7 +730,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { return nil } - private class func provider_query(provider_id: String, start_before: Double?, end_before: Double?) -> CDAKProvider? { + fileprivate class func provider_query(_ provider_id: String, start_before: Double?, end_before: Double?) -> CDAKProvider? { for record in CDAKGlobals.sharedInstance.CDAKRecords { for perf in record.provider_performances { if let provider = perf.provider { @@ -725,9 +755,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } deinit { - for (index, record) in CDAKGlobals.sharedInstance.CDAKRecords.enumerate() { + for (index, record) in CDAKGlobals.sharedInstance.CDAKRecords.enumerated() { if record == self { - CDAKGlobals.sharedInstance.CDAKRecords.removeAtIndex(index) + CDAKGlobals.sharedInstance.CDAKRecords.remove(at: index) break } } @@ -779,9 +809,9 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { //MARK: Copying //http://stackoverflow.com/questions/25808972/how-to-implement-copy-constructor-in-swift-subclass - public func copyWithZone(zone: NSZone) -> AnyObject { // <== NSCopying + open func copy(with zone: NSZone?) -> Any { // <== NSCopying // *** Construct "one of my current class". This is why init() is a required initializer - let theCopy = self.dynamicType.init() + let theCopy = type(of: self).init() theCopy.prefix = self.prefix theCopy.first = self.first @@ -828,7 +858,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { // MARK: Standard properties ///Debugging description - override public var description : String { + override open var description : String { return "CDAKRecord => prefix: \(prefix), first: \(first), last: \(last), suffix: \(suffix), gender: \(gender), birthdate: \(birthdate), deathdate: \(deathdate), religious_affiliation: \(religious_affiliation), effective_time: \(effective_time), race: \(race), ethnicity: \(ethnicity), languages = \(languages), marital_status: \(marital_status), medical_record_number: \(medical_record_number), medical_record_assigner: \(medical_record_assigner), expired: \(expired), clinicalTrialParticipant: \(clinicalTrialParticipant), allergies: \(allergies), care_goals: \(care_goals), conditions: \(conditions), encounters: \(encounters), communications: \(communications), family_history: \(family_history), immunizations: \(immunizations), medical_equipment: \(medical_equipment), medications: \(medications), procedures: \(procedures), results: \(results), social_history: \(social_history), vital_signs: \(vital_signs), advance_directives: \(advance_directives), insurance_providers: \(insurance_providers), functional_statuses: \(functional_statuses), provider_performances: \(provider_performances), addresses: \(addresses), telecoms: \(telecoms)" } @@ -837,7 +867,7 @@ public class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { extension CDAKRecord { // MARK: - Mustache marshalling - override public var mustacheBox: MustacheBox { + override open var mustacheBox: MustacheBox { var vals: [String:MustacheBox] = [String:MustacheBox]() var defaultLanguage: CDAKCodedEntries = CDAKCodedEntries() defaultLanguage.addCodes("IETF", code: "en-US") @@ -921,7 +951,7 @@ extension CDAKRecord { return Box(vals) } - func boxEntries(entries: [CDAKEntry], section: String, status: Bool = false, value: Bool = false) -> MustacheBox? { + func boxEntries(_ entries: [CDAKEntry], section: String, status: Bool = false, value: Bool = false) -> MustacheBox? { if entries.count > 0 { return Box([ "section" : Box(section), @@ -1015,103 +1045,103 @@ extension CDAKRecord: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if identifiers.count > 0 { - dict["identifiers"] = identifiers.map({$0.jsonDict}) + dict["identifiers"] = identifiers.map({$0.jsonDict}) as AnyObject? } if let prefix = prefix { - dict["prefix"] = prefix + dict["prefix"] = prefix as AnyObject? } if let first = first { - dict["first"] = first + dict["first"] = first as AnyObject? } if let last = last { - dict["last"] = last + dict["last"] = last as AnyObject? } if let suffix = suffix { - dict["suffix"] = suffix + dict["suffix"] = suffix as AnyObject? } if let gender = gender { - dict["gender"] = gender + dict["gender"] = gender as AnyObject? } if let birthdate = birthdate { - dict["birthdate"] = birthdate + dict["birthdate"] = birthdate as AnyObject? } if let deathdate = deathdate { - dict["deathdate"] = deathdate + dict["deathdate"] = deathdate as AnyObject? } if religious_affiliation.count > 0 { - dict["religious_affiliation"] = religious_affiliation.codes.map({$0.jsonDict}) + dict["religious_affiliation"] = religious_affiliation.codes.map({$0.jsonDict}) as AnyObject? } if let effective_time = effective_time { - dict["effective_time"] = effective_time + dict["effective_time"] = effective_time as AnyObject? } - dict["id"] = _id + dict["id"] = _id as AnyObject? if let header = header { - dict["header"] = header.jsonDict + dict["header"] = header.jsonDict as AnyObject? } if pregnancies.count > 0 { - dict["pregnancies"] = pregnancies.map({$0.jsonDict}) + dict["pregnancies"] = pregnancies.map({$0.jsonDict}) as AnyObject? } if race.count > 0 { - dict["race"] = race.codes.map({$0.jsonDict}) + dict["race"] = race.codes.map({$0.jsonDict}) as AnyObject? } if ethnicity.count > 0 { - dict["ethnicity"] = ethnicity.codes.map({$0.jsonDict}) + dict["ethnicity"] = ethnicity.codes.map({$0.jsonDict}) as AnyObject? } if languages.count > 0 { - dict["languages"] = languages.map({$0.jsonDict}) + dict["languages"] = languages.map({$0.jsonDict}) as AnyObject? } if marital_status.count > 0 { - dict["marital_status"] = marital_status.codes.map({$0.jsonDict}) + dict["marital_status"] = marital_status.codes.map({$0.jsonDict}) as AnyObject? } if let medical_record_number = medical_record_number { - dict["medical_record_number"] = medical_record_number + dict["medical_record_number"] = medical_record_number as AnyObject? } if let medical_record_assigner = medical_record_assigner { - dict["medical_record_assigner"] = medical_record_assigner + dict["medical_record_assigner"] = medical_record_assigner as AnyObject? } if let expired = expired { - dict["expired"] = expired + dict["expired"] = expired as AnyObject? } if let clinicalTrialParticipant = clinicalTrialParticipant { - dict["clinicalTrialParticipant"] = clinicalTrialParticipant + dict["clinicalTrialParticipant"] = clinicalTrialParticipant as AnyObject? } if let custodian = custodian { - dict["custodian"] = custodian + dict["custodian"] = custodian as AnyObject? } - if allergies.count > 0 { dict["allergies"] = allergies.map({$0.jsonDict}) } - if care_goals.count > 0 { dict["care_goals"] = care_goals.map({$0.jsonDict}) } - if conditions.count > 0 { dict["conditions"] = conditions.map({$0.jsonDict}) } - if encounters.count > 0 { dict["encounters"] = encounters.map({$0.jsonDict}) } - if communications.count > 0 { dict["communications"] = communications.map({$0.jsonDict}) } - if family_history.count > 0 { dict["family_history"] = family_history.map({$0.jsonDict}) } - if immunizations.count > 0 { dict["immunizations"] = immunizations.map({$0.jsonDict}) } - if medical_equipment.count > 0 { dict["medical_equipment"] = medical_equipment.map({$0.jsonDict}) } - if medications.count > 0 { dict["medications"] = medications.map({$0.jsonDict}) } - if procedures.count > 0 { dict["procedures"] = procedures.map({$0.jsonDict}) } - if results.count > 0 { dict["results"] = results.map({$0.jsonDict}) } - if social_history.count > 0 { dict["social_history"] = social_history.map({$0.jsonDict}) } - if vital_signs.count > 0 { dict["vital_signs"] = vital_signs.map({$0.jsonDict}) } - if support.count > 0 { dict["support"] = support.map({$0.jsonDict}) } - if advance_directives.count > 0 { dict["advance_directives"] = advance_directives.map({$0.jsonDict}) } - if insurance_providers.count > 0 { dict["insurance_providers"] = insurance_providers.map({$0.jsonDict}) } - if functional_statuses.count > 0 { dict["functional_statuses"] = functional_statuses.map({$0.jsonDict}) } - if provider_performances.count > 0 { dict["provider_performances"] = provider_performances.map({$0.jsonDict}) } - if addresses.count > 0 { dict["addresses"] = addresses.map({$0.jsonDict}) } - if telecoms.count > 0 { dict["telecoms"] = telecoms.map({$0.jsonDict}) } + if allergies.count > 0 { dict["allergies"] = allergies.map({$0.jsonDict}) as AnyObject? } + if care_goals.count > 0 { dict["care_goals"] = care_goals.map({$0.jsonDict}) as AnyObject?} + if conditions.count > 0 { dict["conditions"] = conditions.map({$0.jsonDict}) as AnyObject? } + if encounters.count > 0 { dict["encounters"] = encounters.map({$0.jsonDict}) as AnyObject? } + if communications.count > 0 { dict["communications"] = communications.map({$0.jsonDict}) as AnyObject? } + if family_history.count > 0 { dict["family_history"] = family_history.map({$0.jsonDict}) as AnyObject? } + if immunizations.count > 0 { dict["immunizations"] = immunizations.map({$0.jsonDict}) as AnyObject? } + if medical_equipment.count > 0 { dict["medical_equipment"] = medical_equipment.map({$0.jsonDict}) as AnyObject?} + if medications.count > 0 { dict["medications"] = medications.map({$0.jsonDict}) as AnyObject? } + if procedures.count > 0 { dict["procedures"] = procedures.map({$0.jsonDict}) as AnyObject? } + if results.count > 0 { dict["results"] = results.map({$0.jsonDict}) as AnyObject? } + if social_history.count > 0 { dict["social_history"] = social_history.map({$0.jsonDict}) as AnyObject? } + if vital_signs.count > 0 { dict["vital_signs"] = vital_signs.map({$0.jsonDict}) as AnyObject? } + if support.count > 0 { dict["support"] = support.map({$0.jsonDict}) as AnyObject? } + if advance_directives.count > 0 { dict["advance_directives"] = advance_directives.map({$0.jsonDict}) as AnyObject? } + if insurance_providers.count > 0 { dict["insurance_providers"] = insurance_providers.map({$0.jsonDict}) as AnyObject?} + if functional_statuses.count > 0 { dict["functional_statuses"] = functional_statuses.map({$0.jsonDict}) as AnyObject?} + if provider_performances.count > 0 { dict["provider_performances"] = provider_performances.map({$0.jsonDict}) as AnyObject?} + if addresses.count > 0 { dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } + if telecoms.count > 0 { dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject?} return dict diff --git a/CDAKit/health-data-standards/lib/models/reference.swift b/CDAKit/health-data-standards/lib/models/reference.swift index de998d1..220ca5d 100644 --- a/CDAKit/health-data-standards/lib/models/reference.swift +++ b/CDAKit/health-data-standards/lib/models/reference.swift @@ -12,18 +12,18 @@ import Foundation /** CDA Reference */ -public class CDAKReference: CDAKJSONInstantiable { +open class CDAKReference: CDAKJSONInstantiable { // MARK: CDA properties ///type - public var type: String? + open var type: String? ///referenced type - public var referenced_type: String = "" + open var referenced_type: String = "" ///reference - public var referenced_id: String = "" + open var referenced_id: String = "" ///Entry - public var entry: CDAKEntry? + open var entry: CDAKEntry? public init(entry: CDAKEntry) { self.entry = entry @@ -47,7 +47,7 @@ public class CDAKReference: CDAKJSONInstantiable { } ///Do not use - will be removed. Was used in HDS Ruby. - private func initFromEventList(event: [String:Any?]) { + fileprivate func initFromEventList(_ event: [String:Any?]) { for (key, value) in event { CDAKUtility.setProperty(self, property: key, value: value) } @@ -61,7 +61,7 @@ public class CDAKReference: CDAKJSONInstantiable { if let entry = self.entry { if let record = entry.record { an_entry = (record.entries.filter({ e in - String(e.dynamicType) == referenced_type && + String(describing: type(of: e)) == referenced_type && e.identifier_as_string == referenced_id })).first } @@ -74,7 +74,7 @@ public class CDAKReference: CDAKJSONInstantiable { if let entry = self.entry { if let record = entry.record { let resolved_reference = (record.entries.filter({ e in - String(e.dynamicType) == referenced_type && + String(describing: type(of: e)) == referenced_type && e.identifier_as_string == referenced_id })).first if let resolved_reference = resolved_reference { @@ -93,14 +93,14 @@ extension CDAKReference: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if let type = type { - dict["type"] = type + dict["type"] = type as AnyObject? } - dict["referenced_type"] = referenced_type - dict["referenced_id"] = referenced_id + dict["referenced_type"] = referenced_type as AnyObject? + dict["referenced_id"] = referenced_id as AnyObject? if let entry = entry { - dict["entry"] = entry.jsonDict + dict["entry"] = entry.jsonDict as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/result_value.swift b/CDAKit/health-data-standards/lib/models/result_value.swift index 9072622..46e2d69 100644 --- a/CDAKit/health-data-standards/lib/models/result_value.swift +++ b/CDAKit/health-data-standards/lib/models/result_value.swift @@ -11,25 +11,25 @@ import Foundation /** Result Value */ -public class CDAKResultValue: NSObject, CDAKThingWithTimes { +open class CDAKResultValue: NSObject, CDAKThingWithTimes { // MARK: CDA properties ///Ad-hoc attributes - public var attributes: [String:String] = [String:String]() + open var attributes: [String:String] = [String:String]() ///time - public var time: Double? + open var time: Double? //this is not originally in the model, but found instances where dynamic properties // were being referfenced for this - see protocol ThingWithTimes ///start time - public var start_time: Double? + open var start_time: Double? ///end time - public var end_time: Double? + open var end_time: Double? // MARK: Standard properties ///Debugging description - override public var description: String { - return "\(self.dynamicType) => attributes: \(attributes), time: \(time), start_time: \(start_time), end_time: \(end_time)" + override open var description: String { + return "\(type(of: self)) => attributes: \(attributes), time: \(time), start_time: \(start_time), end_time: \(end_time)" } } @@ -41,13 +41,13 @@ extension CDAKResultValue: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if let time = time { - dict["time"] = time + dict["time"] = time as AnyObject? } if let start_time = start_time { - dict["start_time"] = start_time + dict["start_time"] = start_time as AnyObject? } if let end_time = end_time { - dict["end_time"] = end_time + dict["end_time"] = end_time as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/social_history.swift b/CDAKit/health-data-standards/lib/models/social_history.swift index 2a6beb9..7f5771d 100644 --- a/CDAKit/health-data-standards/lib/models/social_history.swift +++ b/CDAKit/health-data-standards/lib/models/social_history.swift @@ -14,7 +14,7 @@ Social History [Reference](http://wiki.siframework.org/CDA+-+Social+History+Observation) "The Social History Observation is used to define the patient’s occupational, personal (e.g. lifestyle), social, and environmental history and health risk factors, as well as administrative data such as marital status, race, ethnicity and religious affiliation." */ -public class CDAKSocialHistory: CDAKEntry { +open class CDAKSocialHistory: CDAKEntry { } diff --git a/CDAKit/health-data-standards/lib/models/support.swift b/CDAKit/health-data-standards/lib/models/support.swift index 2ae7931..18675a2 100644 --- a/CDAKit/health-data-standards/lib/models/support.swift +++ b/CDAKit/health-data-standards/lib/models/support.swift @@ -11,31 +11,31 @@ import Foundation /** Support */ -public class CDAKSupport: CDAKEntry { +open class CDAKSupport: CDAKEntry { // MARK: CDA properties ///types of support available - public static let Types = ["Guardian", "Next of Kin", "Caregiver", "Emergency Contact"] + open static let Types = ["Guardian", "Next of Kin", "Caregiver", "Emergency Contact"] ///address - public var address: CDAKAddress? + open var address: CDAKAddress? ///telecom - public var telecom: CDAKTelecom? + open var telecom: CDAKTelecom? ///prefix (was Title) - public var prefix: String? + open var prefix: String? ///first / given name - public var given_name: String? + open var given_name: String? ///family / past name - public var family_name: String? + open var family_name: String? ///suffix - public var suffix: String? + open var suffix: String? ///mother's maiden name - public var mothers_maiden_name: String? + open var mothers_maiden_name: String? ///type (see types) - public var type: String? + open var type: String? ///relationship - public var relationship: String? + open var relationship: String? //# validates_inclusion_of :type, :in => Types @@ -48,34 +48,34 @@ extension CDAKSupport { var dict = super.jsonDict if let address = address { - dict["address"] = address.jsonDict + dict["address"] = address.jsonDict as AnyObject? } if let telecom = telecom { - dict["telecom"] = telecom.jsonDict + dict["telecom"] = telecom.jsonDict as AnyObject? } if let prefix = prefix { - dict["prefix"] = prefix + dict["prefix"] = prefix as AnyObject? } if let given_name = given_name { - dict["given_name"] = given_name + dict["given_name"] = given_name as AnyObject? } if let family_name = family_name { - dict["family_name"] = family_name + dict["family_name"] = family_name as AnyObject? } if let suffix = suffix { - dict["suffix"] = suffix + dict["suffix"] = suffix as AnyObject? } if let mothers_maiden_name = mothers_maiden_name { - dict["mothers_maiden_name"] = mothers_maiden_name + dict["mothers_maiden_name"] = mothers_maiden_name as AnyObject? } if let type = type { - dict["type"] = type + dict["type"] = type as AnyObject? } if let relationship = relationship { - dict["relationship"] = relationship + dict["relationship"] = relationship as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/telecom.swift b/CDAKit/health-data-standards/lib/models/telecom.swift index fedea7f..5f3dcbe 100644 --- a/CDAKit/health-data-standards/lib/models/telecom.swift +++ b/CDAKit/health-data-standards/lib/models/telecom.swift @@ -12,24 +12,24 @@ import Mustache /** Telephone */ -public class CDAKTelecom: NSObject, CDAKJSONInstantiable { +open class CDAKTelecom: NSObject, CDAKJSONInstantiable { // MARK: CDA properties weak var record: CDAKRecord? ///phone use type - public var use: String? + open var use: String? ///phone number - public var value: String? + open var value: String? ///is this the preferred phone? - public var preferred: Bool? + open var preferred: Bool? /** Determines whether the phone is empty */ - public var is_empty: Bool { + open var is_empty: Bool { - let someText: String = "\(value ?? "")".stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) + let someText: String = "\(value ?? "")".trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) if someText.characters.count > 0 { return false @@ -59,7 +59,7 @@ public class CDAKTelecom: NSObject, CDAKJSONInstantiable { } ///Do not use - will be removed. Was used in HDS Ruby. - private func initFromEventList(event: [String:Any?]) { + fileprivate func initFromEventList(_ event: [String:Any?]) { for (key, value) in event { CDAKUtility.setProperty(self, property: key, value: value) } @@ -67,7 +67,7 @@ public class CDAKTelecom: NSObject, CDAKJSONInstantiable { // MARK: Standard properties ///Debugging description - public override var description: String { + open override var description: String { return "CDAKTelecom => use: \(use), value: \(value), preferred: \(preferred)" } @@ -76,11 +76,11 @@ public class CDAKTelecom: NSObject, CDAKJSONInstantiable { extension CDAKTelecom { // MARK: - Mustache marshalling - override public var mustacheBox: MustacheBox { + override open var mustacheBox: MustacheBox { return Box([ "use": use, "value": value, - "preferred": String(preferred) + "preferred": String(describing: preferred) ]) } } @@ -91,13 +91,13 @@ extension CDAKTelecom: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] if let use = use { - dict["use"] = use + dict["use"] = use as AnyObject? } if let value = value { - dict["value"] = value + dict["value"] = value as AnyObject? } if let preferred = preferred { - dict["preferred"] = preferred + dict["preferred"] = preferred as AnyObject? } return dict } diff --git a/CDAKit/health-data-standards/lib/models/thing_with_codes.swift b/CDAKit/health-data-standards/lib/models/thing_with_codes.swift index 2db0ead..932315e 100644 --- a/CDAKit/health-data-standards/lib/models/thing_with_codes.swift +++ b/CDAKit/health-data-standards/lib/models/thing_with_codes.swift @@ -31,16 +31,17 @@ extension CDAKThingWithCodes { return convert_codes_to_s(codes) } - internal func convert_codes_to_s(codes: CDAKCodedEntries) -> String { + internal func convert_codes_to_s(_ codes: CDAKCodedEntries) -> String { // return codes.map { (code_set, codes) in ("\(code_set): " + codes.map({$0.code}).joinWithSeparator(", ")) }.joinWithSeparator(" ") - return codes.map { (code_set, codes) in ("\(code_set): " + codes.map({$0.friendlyNarrativeDescription}).joinWithSeparator(", ")) }.joinWithSeparator(" ") + return codes.map { (code_set, codes) in ("\(code_set): " + codes.map({$0.friendlyNarrativeDescription}).joined(separator: ", ")) }.joined(separator: " ") } /** Will return a single code and code set if one exists in the code sets that are passed in. Returns a hash with a key of code and code_set if found, nil otherwise */ - internal func preferred_code(var preferred_code_sets: [String], codes_attribute: String? = "codes", value_set_map: [CDAKCodedEntries] = []) -> CDAKCodedEntry?//[String:String]? + internal func preferred_code(_ preferred_code_sets: [String], codes_attribute: String? = "codes", value_set_map: [CDAKCodedEntries] = []) -> CDAKCodedEntry?//[String:String]? { + let preferred_code_sets = preferred_code_sets //FIX_ME: - likely issues here with send() and the way I'm pulling this in // count here doesn't really make sense relative to nil, but... @@ -67,7 +68,7 @@ extension CDAKThingWithCodes { } } - if let code_set = Array(Set(preferred_code_sets).intersect(codes.keys)).first { + if let code_set = Array(Set(preferred_code_sets).intersection(codes.keys)).first { return codes[code_set]?.first } //code sets that this entry shares with the requested preferred code set @@ -125,7 +126,7 @@ extension CDAKThingWithCodes { preferred_code_sets looks like... ["SOP", "Source of Payment Typology"] */ - internal func translation_codes(preferred_code_sets: [String], value_set_map: [CDAKCodedEntries] = []) -> CDAKCodedEntries { + internal func translation_codes(_ preferred_code_sets: [String], value_set_map: [CDAKCodedEntries] = []) -> CDAKCodedEntries { var tx_codes: CDAKCodedEntries = CDAKCodedEntries() @@ -151,7 +152,7 @@ extension CDAKThingWithCodes { - returns: all codes that are in the code set */ - internal func codes_in_code_set(code_set: [CDAKCodedEntries]) -> CDAKCodedEntries { + internal func codes_in_code_set(_ code_set: [CDAKCodedEntries]) -> CDAKCodedEntries { var matching: CDAKCodedEntries = CDAKCodedEntries() for some_codes in code_set { @@ -184,8 +185,8 @@ extension CDAKThingWithCodes { - parameter code_system: the code system that the code belongs to */ - internal func add_code(code:Any, code_system:String, code_system_oid: String? = nil, display_name: String? = nil) { - let code_str = String(code) + internal func add_code(_ code:Any, code_system:String, code_system_oid: String? = nil, display_name: String? = nil) { + let code_str = String(describing: code) codes.addCodes(code_system, code: code_str, codeSystemOid: code_system_oid, displayName: display_name) // let code_str = String(code) @@ -209,7 +210,7 @@ extension CDAKThingWithCodes { var dict: [String: AnyObject] = [:] if codes.count > 0 { - dict["codes"] = codes.codes.map({$0.jsonDict}) + dict["codes"] = codes.codes.map({$0.jsonDict}) as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/lib/models/transfer.swift b/CDAKit/health-data-standards/lib/models/transfer.swift index 6a91459..2f8ab3f 100644 --- a/CDAKit/health-data-standards/lib/models/transfer.swift +++ b/CDAKit/health-data-standards/lib/models/transfer.swift @@ -12,17 +12,17 @@ import Mustache /** Represents a transfer event. EX: "transferred to federal holding" */ -public class CDAKTransfer: CDAKThingWithCodes, CustomStringConvertible { +open class CDAKTransfer: CDAKThingWithCodes, CustomStringConvertible { // MARK: CDA properties ///time of transfer - public var time: Double? + open var time: Double? ///codes that define transfer - public var codes = CDAKCodedEntries() + open var codes = CDAKCodedEntries() // MARK: Standard properties ///Debugging description - public var description : String { + open var description : String { return "CDAKTransfer => time: \(time), codes: \(codes)" } } @@ -49,13 +49,13 @@ extension CDAKTransfer: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if codes.count > 0 { - dict["codes"] = codes.codes.map({$0.jsonDict}) + dict["codes"] = codes.codes.map({$0.jsonDict}) as AnyObject? } if let time = time { - dict["time"] = time + dict["time"] = time as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/treating_provider.swift b/CDAKit/health-data-standards/lib/models/treating_provider.swift index f3cbb92..fb17b8d 100644 --- a/CDAKit/health-data-standards/lib/models/treating_provider.swift +++ b/CDAKit/health-data-standards/lib/models/treating_provider.swift @@ -11,12 +11,12 @@ import Foundation /** Information about provider who rendered care */ -public class CDAKTreatingProvider: CDAKEntry { +open class CDAKTreatingProvider: CDAKEntry { // MARK: CDA properties ///identifier - public var treatingProviderID: Int? + open var treatingProviderID: Int? } extension CDAKTreatingProvider { @@ -26,9 +26,9 @@ extension CDAKTreatingProvider { var dict = super.jsonDict if let treatingProviderID = treatingProviderID { - dict["treatingProviderID"] = treatingProviderID + dict["treatingProviderID"] = treatingProviderID as AnyObject? } return dict } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/models/vital_sign.swift b/CDAKit/health-data-standards/lib/models/vital_sign.swift index 31b221e..151d1f8 100644 --- a/CDAKit/health-data-standards/lib/models/vital_sign.swift +++ b/CDAKit/health-data-standards/lib/models/vital_sign.swift @@ -12,12 +12,12 @@ import Foundation Vital signs Inherits all members and methods from CDAKLabResult */ -public class CDAKVitalSign: CDAKLabResult { +open class CDAKVitalSign: CDAKLabResult { // MARK: Standard properties ///Debugging description - override public var description: String { + override open var description: String { return super.description } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/lib/util/code_system_helper.swift b/CDAKit/health-data-standards/lib/util/code_system_helper.swift index 680854a..1dc964d 100644 --- a/CDAKit/health-data-standards/lib/util/code_system_helper.swift +++ b/CDAKit/health-data-standards/lib/util/code_system_helper.swift @@ -11,7 +11,7 @@ import Foundation /** General helpers for working with codes and code system */ -public class CDAKCodeSystemHelper { +open class CDAKCodeSystemHelper { /** code system name for a given code system OID @@ -65,7 +65,7 @@ public class CDAKCodeSystemHelper { EX: "FDA SPL" : "NCI Thesaurus" */ - public static let CODE_SYSTEM_ALIASES: [String:String] = [ + open static let CODE_SYSTEM_ALIASES: [String:String] = [ "FDA SPL" : "NCI Thesaurus", //Structured Product Labeling? "HSLOC" : "HL7 Healthcare Service Location", "SOP" : "Source of Payment Typology", @@ -74,7 +74,7 @@ public class CDAKCodeSystemHelper { /// Some old OID are still around in data, this hash maps retired OID values to /// the new value - public static let OID_ALIASES: [String:String] = [ + open static let OID_ALIASES: [String:String] = [ "2.16.840.1.113883.6.59" : "2.16.840.1.113883.12.292" //# CVX ] @@ -82,7 +82,7 @@ public class CDAKCodeSystemHelper { /// Returns the name of a code system given an oid /// - parameter oid: [String] oid of a code system /// - returns: [String] the name of the code system as described in the measure definition JSON - public class func code_system_for(oid: String) -> String { + open class func code_system_for(_ oid: String) -> String { var an_oid = oid if let an_alias = OID_ALIASES[oid] { an_oid = an_alias @@ -98,7 +98,8 @@ public class CDAKCodeSystemHelper { /// Returns the oid for a code system given a codesystem name /// - parameter code_system: [String] the name of the code system /// - returns: [String] the oid of the code system - public class func oid_for_code_system(var code_system: String) -> String { + public class func oid_for_code_system(_ code_system: String) -> String { + var code_system = code_system if let an_alias = CODE_SYSTEM_ALIASES[code_system] { code_system = an_alias @@ -115,7 +116,7 @@ public class CDAKCodeSystemHelper { /// Returns the whole map of OIDs to code systems /// - returns: [Hash] oids as keys, code system names as values - public class func code_systems() -> [String:String] { + open class func code_systems() -> [String:String] { return CDAKGlobals.sharedInstance.CDAK_EXTENDED_CODE_SYSTEMS } @@ -124,7 +125,7 @@ public class CDAKCodeSystemHelper { This can be used manually or happens automatically as code system/oid pairs are discovered during CDA import */ - public class func addCodeSystem(code_system: String, oid: String? = "UNK") { + open class func addCodeSystem(_ code_system: String, oid: String? = "UNK") { if let oid = oid { if let _ = CDAKGlobals.sharedInstance.CDAK_EXTENDED_CODE_SYSTEMS[oid] { //we already have this code system diff --git a/CDAKit/health-data-standards/lib/util/hl7_helper.swift b/CDAKit/health-data-standards/lib/util/hl7_helper.swift index 1e358fa..04dc864 100644 --- a/CDAKit/health-data-standards/lib/util/hl7_helper.swift +++ b/CDAKit/health-data-standards/lib/util/hl7_helper.swift @@ -11,33 +11,83 @@ import Foundation /** Assistive functions to help conform to HL7 formats */ -public class CDAKHL7Helper { +open class CDAKHL7Helper { /** Converts an HL7 timestamp into an Integer - parameter timestamp: [String] the HL7 timestamp. Expects YYYYMMDD format - returns: [Integer] Date in seconds since the epoch */ - public class func timestamp_to_integer(timestamp: String?) -> Double? { + open class func timestamp_to_integer(_ timestamp: String?) -> Double? { - if let timestamp = timestamp { - if timestamp.characters.count >= 4 { - let year = timestamp[0...3] - let month = timestamp.characters.count >= 6 ? timestamp[4...5] : "01" - let day = timestamp.characters.count >= 8 ? timestamp[6...7] : "01" - let hour = timestamp.characters.count >= 10 ? timestamp[8...9] : "00" - let min = timestamp.characters.count >= 12 ? timestamp[10...11] : "00" - let sec = timestamp.characters.count >= 14 ? timestamp[12...13] : "00" + if let _timestamp = timestamp { + if _timestamp.characters.count >= 4 { + + let index = _timestamp.index(_timestamp.startIndex, offsetBy: 4) + let year = _timestamp.substring(to: index) // _timestamp[0...3] + + var month = "01" + if _timestamp.characters.count >= 6 { + let start = _timestamp.index(_timestamp.startIndex, offsetBy: 4) + let end = _timestamp.index(_timestamp.startIndex, offsetBy: 6) + let range = start..= 6 ? _timestamp[4...5] : "01" + + var day = "01" + if _timestamp.characters.count >= 8 { + let start = _timestamp.index(_timestamp.startIndex, offsetBy: 6) + let end = _timestamp.index(_timestamp.startIndex, offsetBy: 8) + let range = start..= 10 { + let start = _timestamp.index(_timestamp.startIndex, offsetBy: 8) + let end = _timestamp.index(_timestamp.startIndex, offsetBy: 10) + let range = start..= 10 ? _timestamp[8...9] : "00" + + var min = "00" + if _timestamp.characters.count >= 12 { + let start = _timestamp.index(_timestamp.startIndex, offsetBy: 10) + let end = _timestamp.index(_timestamp.startIndex, offsetBy: 12) + let range = start..= 12 ? _timestamp[10...11] : "00" + + var sec = "00" + if _timestamp.characters.count >= 14 { + let start = _timestamp.index(_timestamp.startIndex, offsetBy: 12) + let end = _timestamp.index(_timestamp.startIndex, offsetBy: 14) + let range = start..= 14 ? _timestamp[12...13] : "00" + + let dateString = ("\(year)\(month)\(day)\(hour)\(min)\(sec)") - let dateStringFormatter = NSDateFormatter() + let dateStringFormatter = DateFormatter() dateStringFormatter.dateFormat = "yyyyMMddHHmmss" - dateStringFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - dateStringFormatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! + dateStringFormatter.timeZone = TimeZone(secondsFromGMT: 0) + dateStringFormatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601) - dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") - let d = dateStringFormatter.dateFromString(dateString) + dateStringFormatter.locale = Locale(identifier: "en_US_POSIX") + let d = dateStringFormatter.date(from: dateString) if let d = d { return d.timeIntervalSince1970 @@ -48,4 +98,4 @@ public class CDAKHL7Helper { return nil } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/swift_helpers/CDAKCodedEntries.swift b/CDAKit/health-data-standards/swift_helpers/CDAKCodedEntries.swift index 8aa9a12..8302995 100644 --- a/CDAKit/health-data-standards/swift_helpers/CDAKCodedEntries.swift +++ b/CDAKit/health-data-standards/swift_helpers/CDAKCodedEntries.swift @@ -41,7 +41,7 @@ public struct CDAKCodedEntry: CustomStringConvertible, Equatable, Hashable { ///The specific vocabulary code for the term public var code: String - private var _displayName: String? + fileprivate var _displayName: String? ///the human-readable description for the term public var displayName: String? { get { @@ -59,7 +59,7 @@ public struct CDAKCodedEntry: CustomStringConvertible, Equatable, Hashable { return "\(code)\(displayName != nil ? (" (" + displayName! + ")") : "")" } - private var _codeSystemOid: String? + fileprivate var _codeSystemOid: String? /// OID for the specified vocabulary. Optional. Will be automatically looked up by codeSystem key if value is nil public var codeSystemOid: String? { get { @@ -136,19 +136,35 @@ extension CDAKCodedEntry: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] - dict["codeSystem"] = codeSystem + dict["codeSystem"] = codeSystem as AnyObject? if let codeSystemOid = codeSystemOid { - dict["codeSystemOid"] = codeSystemOid + dict["codeSystemOid"] = codeSystemOid as AnyObject? } if let displayName = displayName { - dict["displayName"] = displayName + dict["displayName"] = displayName as AnyObject? } - dict["code"] = code + dict["code"] = code as AnyObject? return dict } } +struct MyCollectionType : Collection { + + typealias Index = Int + var startIndex : Index { return 0 } + var endIndex : Index { return 3 } + + subscript(position : Int) -> String { + return "I am element #\(position)" + } + + func index(after i: Int) -> Int { + guard i != endIndex else { fatalError("Cannot increment endIndex") } + return i + 1 + } +} + /** Represents a collection of vocabulary concepts for an entry. @@ -165,29 +181,395 @@ extension CDAKCodedEntry: CDAKJSONExportable { */ -public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, CollectionType, Equatable, Hashable { + +public struct CDAKCodedEntries : Collection, Sequence, CustomStringConvertible, Equatable, Hashable { + + fileprivate var entries: [String:[CDAKCodedEntry]] = [:] + + ///Returns all entries across all vocabularies + public var codes: [CDAKCodedEntry] { + get { return entries.flatMap({$0.1}) } + } + + public typealias Index = Dictionary.Index + public typealias Element = (String, [CDAKCodedEntry]) + + public var startIndex : Index { return entries.startIndex } + public var endIndex : Index { return entries.endIndex } + + + public subscript(position : Index) -> Element { + return entries[position] + } + + public func index(after i: Index) -> Index { + guard i != endIndex else { fatalError("Cannot increment endIndex") } + return entries.index(after: i) + } + + + //MARK: Dictionary Generator properties and methods + //public func makeIterator() -> DictionaryIterator /* Index */ { + // return entries.makeIterator() + //} + + //public func makeIterator() -> IndexingIterator { + // + //} + + ///first entry + public var first: Element? { get {return entries.first} } + + ///number of entries + public var count: Int { get {return entries.count} } + + ///vocabulary system keys/tags + public var keys: [String] { return codeSystems } + + fileprivate var _codeSystems: Set = Set() + + //public func prefix(upTo end: DictionaryIndex) -> Slice { + // return entries.prefix(upTo: end) + //} + + ///All vocabulary code system keys/tags used in current entries + public var codeSystems: [String] { + get { return Array(_codeSystems) } + //set { _codeSystems = Set(newValue) } + } + + // MARK: Standard properties + ///Debugging description + public var description: String { + return (self.entries.description) + } + + ///hash value + public var hashValue: Int { + var a_hash: Int = 0 + for code in codes { + a_hash = a_hash ^ code.hashValue + } + return a_hash + } + + + + ///If you need to manage the notion of preferred codes or translation codes at the code level (as opposed to the entry level), then you can do so by supplying a list of code system keys/tags as Strings. EX: "LOINC", "SNOMED-CT". These will then be "preferred" code systems. + public var preferred_code_sets: [String] = [] + + ///If you have supplied preferred code sets, you can then export the first matching preferred term for that set of code sets + public var preferred_code: CDAKCodedEntry? { + get { + return entries.flatMap({$0.1}).filter({preferred_code_sets.contains($0.codeSystem)}).sorted(by: {$0.0.code < $0.1.code}).first + } + } + + + ///If you have supplied preferred code sets, you can emit the list of translation codes for the entry + public var translation_codes: [CDAKCodedEntry] { + get { + return entries.flatMap({$0.1}).filter({$0 != preferred_code}) + } + } + + + //MARK: Initializers + ///Basic initializer + public init(){} + /** + Basic initializer + + - parameter codeSystem: the vocabulary key/tag. EX: "SNOMED-CT" + - parameter code: the vocabulary concept code + - parameter codeSystemOid: the OID associated with the vocabulary. If it is not supplied, the OID will be looked up based on the supplied vocabulary codeSystem + - parameter displayName: the human-readable concept description + */ + public init(codeSystem:String, code: String, codeSystemOid: String? = nil, displayName: String? = nil){ + addCodes(codeSystem, code: code, codeSystemOid: codeSystemOid, displayName: displayName) + } + /** + Basic initializer + + - parameter entries: Accepts an array of coded entries + */ + public init(entries: [CDAKCodedEntry]) { + for entry in entries { + addCodes(entry.codeSystem, code: entry.code, codeSystemOid: entry.codeSystemOid, displayName: entry.displayName) + } + } + /** + Basic initializer + + - parameter entry: Accepts an optional coded entry + */ + public init(entry: CDAKCodedEntry?) { + if let entry = entry { + addCodes(entry.codeSystem, code: entry.code, codeSystemOid: entry.codeSystemOid, displayName: entry.displayName) + } + } + + + // we may want to remove a bunch of entries from a set + mutating func removeCodes(foundInEntries set1: CDAKCodedEntries) { + if let matchingCodes = findIntersectingCodedEntries(forCodedEntries: set1) { + for c in matchingCodes { + if let index = entries[c.codeSystem]!.index(of: c) { + entries[c.codeSystem]!.remove(at: index) + } + } + } + } + + /** + Add a code to the vocabulary collection + - parameter entries: an array of coded entries + */ + mutating public func addCodes(_ entries: [CDAKCodedEntry]) { + for entry in entries { + addCodes(entry.codeSystem, code: entry.code, codeSystemOid: entry.codeSystemOid, displayName: entry.displayName) + } + } + + /** + Add a code to the vocabulary collection + - parameter entries: an optional coded entry + */ + mutating public func addCodes(_ entry: CDAKCodedEntry?) { + if let entry = entry { + addCodes(entry.codeSystem, code: entry.code, codeSystemOid: entry.codeSystemOid, displayName: entry.displayName) + } + } + + + + /** + Primary method to add a code to the vocabulary collection + + If a code with the same vocabulary key/tag and code already exists and the new description is non-nil, this will overwrite the existing description with the new one. + + - parameter codeSystem: the vocabulary key/tag. EX: "SNOMED-CT" + - parameter code: the vocabulary concept code + - parameter codeSystemOid: the OID associated with the vocabulary. If it is not supplied, the OID will be looked up based on the supplied vocabulary codeSystem + - parameter displayName: the human-readable concept description + */ + mutating public func addCodes(_ codeSystem: String, code: String, codeSystemOid: String? = nil, displayName: String? = nil) { + //primary function for adding codes + var aNewCode = CDAKCodedEntry(codeSystem: codeSystem, code: code, codeSystemOid: codeSystemOid, displayName: displayName) + + self._codeSystems.insert(codeSystem) + + if self.entries[codeSystem] != nil { + if let index = entries[codeSystem]!.index(of: aNewCode) { + // this code is already in the collection, so we're going to see if the description is populated + // if the old term has a displayName and this one is nil, then we're going to keep the old term + // otherwise, we're going to overwrite whatever exists with this term instead + print("this code already exists") + + if let displayName = entries[codeSystem]![index].displayName { + aNewCode.displayName = displayName + } + entries[codeSystem]![index] = aNewCode + + } else { + self.entries[codeSystem]?.append(aNewCode) + } + } else { + //add new code system key and then add term + self.entries[codeSystem] = [aNewCode] + } + + } + + ///Subscript to return all coded entries based on vocabulary key/tag + public subscript(codeSystem: String) -> [CDAKCodedEntry]? { + get { + return self.entries[codeSystem] + } + set(newValue) { + if newValue == nil { + self.entries.removeValue(forKey: codeSystem) + self._codeSystems = Set(self.codeSystems.filter {$0 != codeSystem}) + return + } + + let oldValue = self.entries.updateValue(newValue!, forKey: codeSystem) + if oldValue == nil { + self._codeSystems.insert(codeSystem) + } + } + } + + + /** + Searches all codeded entries for a match of the specified vocabulary and codes + - parameter forCodeSystem: (String) key for code system. EX: "LOINC" + - parameter matchingCodes: [String] array of strings for code values + - returns: an array of CDAKCodedEntry containing the specified codeSystem:code(s) + */ + public func findIntersectingCodedEntries(forCodeSystem codeSystem: String, matchingCodes codes:[String]) -> [CDAKCodedEntry]? { + if let someEntries = entries[codeSystem] { + return someEntries.filter({ entry in codes.contains(entry.code)}) + } + return nil + } + + /** + Searches all codeded entries for a match of the specified vocabulary and codes + - parameter forCodedEntries: Array of [CDAKCodedEntry] + - returns: an array of CDAKCodedEntry containing the specified codeSystem:code(s) + */ + public func findIntersectingCodedEntries(forCodedEntries matching:[CDAKCodedEntry]?) -> [CDAKCodedEntry]? { + if let matching = matching { + return matching.filter({m in codes.contains(m)}) + } + return nil + } + + + /** + Evaluates existing entries to determine if the supplied concept key/tag and code already exist in the entry collection + + - parameter withCodeSystem (codeSystem): the vocabulary key/tag. EX: "SNOMED-CT" + - parameter andCode (code): the vocabulary concept code + + */ + public func containsCode(withCodeSystem codeSystem: String, andCode code: String) -> Bool { + if let ces = entries[codeSystem]?.contains(CDAKCodedEntry(codeSystem: codeSystem, code: code)){ + return ces + } + return false + } + + /** + Evaluates existing entries to determine if the supplied concept already exists in the entry collection + + - parameter codedEntry: the concept you wish to compare against the existing entry collection + + */ + public func containsCode(_ codedEntry: CDAKCodedEntry) -> Bool { + if let ces = entries[codedEntry.codeSystem]?.contains(codedEntry){ + return ces + } + return false + } + + + /** + Searches all codeded entries for a match of the specified vocabulary and codes + - parameter forCodedEntries: CDAKCodedEntries + - returns: an array of CDAKCodedEntry containing the specified codeSystem:code(s) + */ + public func findIntersectingCodedEntries(forCodedEntries ces:CDAKCodedEntries?) -> [CDAKCodedEntry]? { + if let ces = ces { + return findIntersectingCodedEntries(forCodedEntries: ces.codes) + } + return nil + } + + /** + Counts all distinct entries across all vocabularies. Where `count` would return the number of vocabulary keys/tags, `numberOfDistinctCodes` returns the number of distinct codes. + */ + public var numberOfDistinctCodes: Int { + return entries.flatMap({$0.1}).count + } + + + + +/*********************** + //public struct CDAKCodedEntries: Collection /* CustomStringConvertible, Sequence, Collection, Equatable, Hashable */ { + + //MARK: Dictionary Generator properties and methods + public func makeIterator() -> DictionaryIterator { + return entries.makeIterator() + } + + + ///provides access to coded entries by vocabularykey/tag + //public subscript(_i: Index) -> _Element {get { return entries[_i] }} + //public subscript(position: Index) -> Element {get { return entries[position] }} + + //public subscript(bounds: Range) -> Self.SubSequence { get { return entries.subscript(bounds)} } + + + + + + // var entry_preferred_code : CDAKCodedEntry? + // var code_system_oid = "" + // if let a_preferred_code = preferred_code(preferred_code_sets) { + // //legacy Ruby approach + // let code_set = a_preferred_code.codeSystem + // code_system_oid = CDAKCodeSystemHelper.oid_for_code_system(code_set) + // entry_preferred_code = a_preferred_code + // } + // var entry_translation_codes: CDAKCodedEntries? = self.codes + // if entry_preferred_code != nil { + // entry_translation_codes = self.translation_codes(self.preferred_code_sets) + // } + + + + + public func formIndex(after i: inout DictionaryIndex) { + + } +******/ +} + +/****** +public struct CDAKCodedEntries : Collection { + fileprivate var entries: [String:[CDAKCodedEntry]] = [:] + + public typealias Index = Dictionary.Index + public typealias Element = (String, [CDAKCodedEntry]) + + public var startIndex : Index { return entries.startIndex } + public var endIndex : Index { return entries.endIndex } + + + public subscript(position : Index) -> Element { + return entries[position] + } + + public func index(after i: Index) -> Index { + guard i != endIndex else { fatalError("Cannot increment endIndex") } + return entries.index(after: i) + } +//} + + +//public struct CDAKCodedEntries: Collection /* CustomStringConvertible, Sequence, Collection, Equatable, Hashable */ { //MARK: Dictionary Generator properties and methods - public func generate() -> DictionaryGenerator { - return entries.generate() + public func makeIterator() -> DictionaryIterator { + return entries.makeIterator() } - public typealias Index = Dictionary.Index - public typealias _Element = (String, [CDAKCodedEntry]) - public var startIndex: Index {get { return entries.startIndex }} - public var endIndex: Index {get { return entries.endIndex }} - ///provides access to coded entries by vocabulary key/tag - public subscript(_i: Index) -> _Element {get { return entries[_i] }} + //public typealias Index = Dictionary.Index + //public typealias Element = (String, [CDAKCodedEntry]) + //public var startIndex: Index {get { return entries.startIndex }} + //public var endIndex: Index {get { return entries.endIndex }} + ///provides access to coded entries by vocabularykey/tag + //public subscript(_i: Index) -> _Element {get { return entries[_i] }} + //public subscript(position: Index) -> Element {get { return entries[position] }} + + //public subscript(bounds: Range) -> Self.SubSequence { get { return entries.subscript(bounds)} } + ///first entry - public var first: _Element? { get {return entries.first} } + public var first: Element? { get {return entries.first} } ///number of entries public var count: Int { get {return entries.count} } ///vocabulary system keys/tags public var keys: [String] { return codeSystems } - private var _codeSystems: Set = Set() - private var entries: [String:[CDAKCodedEntry]] = [:] - + fileprivate var _codeSystems: Set = Set() + //fileprivate var entries: [String:[CDAKCodedEntry]] = [:] + + //public func prefix(upTo end: DictionaryIndex) -> Slice { + // return entries.prefix(upTo: end) + //} ///All vocabulary code system keys/tags used in current entries public var codeSystems: [String] { get { return Array(_codeSystems) } @@ -205,7 +587,7 @@ public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, Collectio ///If you have supplied preferred code sets, you can then export the first matching preferred term for that set of code sets public var preferred_code: CDAKCodedEntry? { get { - return entries.flatMap({$0.1}).filter({preferred_code_sets.contains($0.codeSystem)}).sort({$0.0.code < $0.1.code}).first + return entries.flatMap({$0.1}).filter({preferred_code_sets.contains($0.codeSystem)}).sorted(by: {$0.0.code < $0.1.code}).first } } @@ -264,7 +646,12 @@ public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, Collectio addCodes(entry.codeSystem, code: entry.code, codeSystemOid: entry.codeSystemOid, displayName: entry.displayName) } } - + + public func index(after i: Index) -> Index { + guard i != endIndex else { fatalError("Cannot increment endIndex") } + return entries.index(after: i) + } + ///Subscript to return all coded entries based on vocabulary key/tag public subscript(codeSystem: String) -> [CDAKCodedEntry]? { get { @@ -272,7 +659,7 @@ public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, Collectio } set(newValue) { if newValue == nil { - self.entries.removeValueForKey(codeSystem) + self.entries.removeValue(forKey: codeSystem) self._codeSystems = Set(self.codeSystems.filter {$0 != codeSystem}) return } @@ -288,8 +675,8 @@ public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, Collectio mutating func removeCodes(foundInEntries set1: CDAKCodedEntries) { if let matchingCodes = findIntersectingCodedEntries(forCodedEntries: set1) { for c in matchingCodes { - if let index = entries[c.codeSystem]!.indexOf(c) { - entries[c.codeSystem]!.removeAtIndex(index) + if let index = entries[c.codeSystem]!.index(of: c) { + entries[c.codeSystem]!.remove(at: index) } } } @@ -299,7 +686,7 @@ public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, Collectio Add a code to the vocabulary collection - parameter entries: an array of coded entries */ - mutating public func addCodes(entries: [CDAKCodedEntry]) { + mutating public func addCodes(_ entries: [CDAKCodedEntry]) { for entry in entries { addCodes(entry.codeSystem, code: entry.code, codeSystemOid: entry.codeSystemOid, displayName: entry.displayName) } @@ -309,7 +696,7 @@ public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, Collectio Add a code to the vocabulary collection - parameter entries: an optional coded entry */ - mutating public func addCodes(entry: CDAKCodedEntry?) { + mutating public func addCodes(_ entry: CDAKCodedEntry?) { if let entry = entry { addCodes(entry.codeSystem, code: entry.code, codeSystemOid: entry.codeSystemOid, displayName: entry.displayName) } @@ -325,14 +712,14 @@ public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, Collectio - parameter codeSystemOid: the OID associated with the vocabulary. If it is not supplied, the OID will be looked up based on the supplied vocabulary codeSystem - parameter displayName: the human-readable concept description */ - mutating public func addCodes(codeSystem: String, code: String, codeSystemOid: String? = nil, displayName: String? = nil) { + mutating public func addCodes(_ codeSystem: String, code: String, codeSystemOid: String? = nil, displayName: String? = nil) { //primary function for adding codes var aNewCode = CDAKCodedEntry(codeSystem: codeSystem, code: code, codeSystemOid: codeSystemOid, displayName: displayName) self._codeSystems.insert(codeSystem) if self.entries[codeSystem] != nil { - if let index = entries[codeSystem]!.indexOf(aNewCode) { + if let index = entries[codeSystem]!.index(of: aNewCode) { // this code is already in the collection, so we're going to see if the description is populated // if the old term has a displayName and this one is nil, then we're going to keep the old term // otherwise, we're going to overwrite whatever exists with this term instead @@ -372,7 +759,7 @@ public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, Collectio - parameter codedEntry: the concept you wish to compare against the existing entry collection */ - public func containsCode(codedEntry: CDAKCodedEntry) -> Bool { + public func containsCode(_ codedEntry: CDAKCodedEntry) -> Bool { if let ces = entries[codedEntry.codeSystem]?.contains(codedEntry){ return ces } @@ -439,10 +826,14 @@ public struct CDAKCodedEntries: CustomStringConvertible, SequenceType, Collectio return a_hash } + public func formIndex(after i: inout DictionaryIndex) { + } } + ***/ + //Equality comparison for CodedEntries public func == (lhs: CDAKCodedEntries, rhs: CDAKCodedEntries) -> Bool { return lhs.hashValue == rhs.hashValue @@ -474,7 +865,7 @@ extension CDAKCodedEntries: CDAKJSONExportable { public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] - dict["entries"] = codes.map({$0.jsonDict}) + dict["entries"] = codes.map({$0.jsonDict}) as AnyObject? return dict } diff --git a/CDAKit/health-data-standards/swift_helpers/CDAKCommonUtility.swift b/CDAKit/health-data-standards/swift_helpers/CDAKCommonUtility.swift index b29912a..17eb9b3 100644 --- a/CDAKit/health-data-standards/swift_helpers/CDAKCommonUtility.swift +++ b/CDAKit/health-data-standards/swift_helpers/CDAKCommonUtility.swift @@ -11,12 +11,12 @@ import Foundation class CDAKCommonUtility { static let podName = "CDAKit" - static var bundle: NSBundle { + static var bundle: Bundle { - let frameworkBundle = NSBundle(forClass: CDAKCommonUtility.self) + let frameworkBundle = Bundle(for: CDAKCommonUtility.self) //if we're in a pod, look for our own bundle in the parent project - if let bundlePath = frameworkBundle.pathForResource(podName, ofType: "bundle") { - if let myBundle = NSBundle.init(path: bundlePath) { + if let bundlePath = frameworkBundle.path(forResource: podName, ofType: "bundle") { + if let myBundle = Bundle.init(path: bundlePath) { //print("CDAKCommonUtility -> myBundle.bundlePath = '\(myBundle.bundlePath)'") return myBundle } @@ -26,10 +26,10 @@ class CDAKCommonUtility { return frameworkBundle } - class func classNameAsString(obj: Any, removeOptional: Bool = true) -> String { + class func classNameAsString(_ obj: Any, removeOptional: Bool = true) -> String { // //prints more readable results for dictionaries, arrays, Int, etc - var class_name = String(obj.dynamicType).componentsSeparatedByString(".").last! - if removeOptional == true && class_name.containsString("Optional") { + var class_name = String(describing: type(of: (obj) as AnyObject)).components(separatedBy: ".").last! + if removeOptional == true && class_name.contains("Optional") { class_name = CDAKCommonUtility.Regex.replaceMatches("(?:^|\")([^\"]*)(?:$|\")", inString: class_name, withString: "")! } @@ -40,19 +40,19 @@ class CDAKCommonUtility { class Regex { //from Ray Wenderlich's example - really nice stuff - class func listGroups(pattern: String, inString string: String) -> [String] { + class func listGroups(_ pattern: String, inString string: String) -> [String] { var groupMatches = [String]() do { let regex = try NSRegularExpression(pattern: pattern, options: []) let range = NSMakeRange(0, string.characters.count) - let matches = regex.matchesInString(string, options: [], range: range) + let matches = regex.matches(in: string, options: [], range: range) for match in matches { let rangeCount = match.numberOfRanges for group in 0.. String? { + class func replaceMatches(_ pattern: String, inString string: String, withString replacementString: String) -> String? { do { let regex = try NSRegularExpression(pattern: pattern, options: []) let range = NSMakeRange(0, string.characters.count) - return regex.stringByReplacingMatchesInString(string, options: [], range: range, withTemplate: replacementString) + return regex.stringByReplacingMatches(in: string, options: [], range: range, withTemplate: replacementString) } catch { fatalError("replaceMatches Exception with pattern '\(pattern)'") @@ -76,15 +76,15 @@ class CDAKCommonUtility { } //from Ray Wenderlich - class func listMatches(pattern: String, inString string: String) -> [String] { + class func listMatches(_ pattern: String, inString string: String) -> [String] { do { let regex = try NSRegularExpression(pattern: pattern, options: []) let range = NSMakeRange(0, string.characters.count) - let matches = regex.matchesInString(string, options: [], range: range) + let matches = regex.matches(in: string, options: [], range: range) return matches.map { let range = $0.range - return (string as NSString).substringWithRange(range) + return (string as NSString).substring(with: range) } } catch { @@ -93,11 +93,11 @@ class CDAKCommonUtility { } //from Ray Wenderlich - class func containsMatch(pattern: String, inString string: String) -> Bool { + class func containsMatch(_ pattern: String, inString string: String) -> Bool { do { let regex = try NSRegularExpression(pattern: pattern, options: [] ) let range = NSMakeRange(0, string.characters.count) - return regex.firstMatchInString(string, options: [], range: range) != nil + return regex.firstMatch(in: string, options: [], range: range) != nil } catch { fatalError("containsMatch Exception with pattern '\(pattern)' ") @@ -108,14 +108,14 @@ class CDAKCommonUtility { - class func load_json_from_file(filename:String) -> NSDictionary + class func load_json_from_file(_ filename:String) -> NSDictionary { - let path = NSBundle.mainBundle().pathForResource(filename, ofType: "json") + let path = Bundle.main.path(forResource: filename, ofType: "json") if let path = path { do { - let jsonData = try NSData(contentsOfFile: path, options: NSDataReadingOptions.DataReadingMappedIfSafe) - let jsonResult = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary + let jsonData = try Data(contentsOf: URL(fileURLWithPath: path), options: NSData.ReadingOptions.mappedIfSafe) + let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary return jsonResult } @@ -129,12 +129,12 @@ class CDAKCommonUtility { } } - class func load_xml_data_from_file(filename: String) -> NSData + class func load_xml_data_from_file(_ filename: String) -> Data { - let filepath = NSBundle.mainBundle().pathForResource(filename, ofType: "xml") + let filepath = Bundle.main.path(forResource: filename, ofType: "xml") if let filepath = filepath { - if let data = NSData(contentsOfURL: NSURL(fileURLWithPath: filepath)) + if let data = try? Data(contentsOf: URL(fileURLWithPath: filepath)) { return data } @@ -149,11 +149,11 @@ class CDAKCommonUtility { } } - class func load_xml_string_from_file(filename: String) -> String + class func load_xml_string_from_file(_ filename: String) -> String { let data = CDAKCommonUtility.load_xml_data_from_file(filename) - if let xml = NSString(data: data, encoding: NSUTF8StringEncoding) as? String + if let xml = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as? String { return xml } @@ -164,15 +164,15 @@ class CDAKCommonUtility { } //https://medium.com/swift-programming/4-json-in-swift-144bf5f88ce4 - class func JSONStringify(value: AnyObject, prettyPrinted: Bool = false) -> String { + class func JSONStringify(_ value: AnyObject, prettyPrinted: Bool = false) -> String { //var options = prettyPrinted ? NSJSONWritingOptions.PrettyPrinted : nil let options = prettyPrinted ? - NSJSONWritingOptions.PrettyPrinted : NSJSONWritingOptions(rawValue: 0) + JSONSerialization.WritingOptions.prettyPrinted : JSONSerialization.WritingOptions(rawValue: 0) - if NSJSONSerialization.isValidJSONObject(value) { + if JSONSerialization.isValidJSONObject(value) { do { - let data = try NSJSONSerialization.dataWithJSONObject(value, options: options) - if let string = NSString(data: data, encoding: NSUTF8StringEncoding) { + let data = try JSONSerialization.data(withJSONObject: value, options: options) + if let string = NSString(data: data, encoding: String.Encoding.utf8.rawValue) { return string as String } } @@ -183,10 +183,10 @@ class CDAKCommonUtility { } //https://medium.com/swift-programming/4-json-in-swift-144bf5f88ce4 - class func JSONParseDictionary(jsonString: String) -> [String: AnyObject] { - if let data = jsonString.dataUsingEncoding(NSUTF8StringEncoding) { + class func JSONParseDictionary(_ jsonString: String) -> [String: AnyObject] { + if let data = jsonString.data(using: String.Encoding.utf8) { do { - let dictionary = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0)) as? [String: AnyObject] + let dictionary = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions(rawValue: 0)) as? [String: AnyObject] return dictionary! } catch { @@ -198,24 +198,24 @@ class CDAKCommonUtility { //http://api.rubyonrails.org/classes/ERB/Util.html //https://github.com/Halotis/EscapeHTML/blob/master/EscapeHTML/EscapeHTML.swift - class func html_escape(html: String?) -> String{ + class func html_escape(_ html: String?) -> String{ if let html = html { - var result = html.stringByReplacingOccurrencesOfString("&", withString: "&", options: [], range: nil) - result = result.stringByReplacingOccurrencesOfString("\"", withString: """, options: [], range: nil) - result = result.stringByReplacingOccurrencesOfString("'", withString: "'", options: [], range: nil) - result = result.stringByReplacingOccurrencesOfString("<", withString: "<", options: [], range: nil) - result = result.stringByReplacingOccurrencesOfString(">", withString: ">", options: [], range: nil) + var result = html.replacingOccurrences(of: "&", with: "&", options: [], range: nil) + result = result.replacingOccurrences(of: "\"", with: """, options: [], range: nil) + result = result.replacingOccurrences(of: "'", with: "'", options: [], range: nil) + result = result.replacingOccurrences(of: "<", with: "<", options: [], range: nil) + result = result.replacingOccurrences(of: ">", with: ">", options: [], range: nil) return result } return "" } - class func jsonStringFromDict(jsonDict: [String:AnyObject]) -> String? { - if NSJSONSerialization.isValidJSONObject(jsonDict) { // True + class func jsonStringFromDict(_ jsonDict: [String:AnyObject]) -> String? { + if JSONSerialization.isValidJSONObject(jsonDict) { // True do { - let rawData = try NSJSONSerialization.dataWithJSONObject(jsonDict, options: .PrettyPrinted) - let jsonString = NSString(data: rawData, encoding: NSUTF8StringEncoding) as? String - return NSString(data: rawData, encoding: NSUTF8StringEncoding) as? String + let rawData = try JSONSerialization.data(withJSONObject: jsonDict, options: .prettyPrinted) + let jsonString = NSString(data: rawData, encoding: String.Encoding.utf8.rawValue) as? String + return NSString(data: rawData, encoding: String.Encoding.utf8.rawValue) as? String } catch let error as NSError { print(error) } @@ -226,4 +226,4 @@ class CDAKCommonUtility { } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/swift_helpers/CDAKGlobalData.swift b/CDAKit/health-data-standards/swift_helpers/CDAKGlobalData.swift index e0401c4..09fe578 100644 --- a/CDAKit/health-data-standards/swift_helpers/CDAKGlobalData.swift +++ b/CDAKit/health-data-standards/swift_helpers/CDAKGlobalData.swift @@ -13,12 +13,12 @@ import Foundation /** Stores and manages all cross-record data and settings for CDA import and export */ -public class CDAKGlobals { +open class CDAKGlobals { ///allows access to all global properties - public static let sharedInstance = CDAKGlobals() + open static let sharedInstance = CDAKGlobals() - private init() { + fileprivate init() { //CDAKDefaultMetadata = CDAKQRDAHeader() //CDAKDefaultMetadata.confidentiality = .Normal } @@ -28,7 +28,7 @@ public class CDAKGlobals { If Record-specific metadata is found, that will be used instead. */ - public var CDAKDefaultMetadata: CDAKQRDAHeader? + open var CDAKDefaultMetadata: CDAKQRDAHeader? /** @@ -38,7 +38,7 @@ public class CDAKGlobals { The default value is "false." You will need to explicitly enable this if you want to attempt to import unknown document types. */ - public var attemptNonStandardCDAImport = false + open var attemptNonStandardCDAImport = false /** Returns all providers discovered during import of all records. @@ -84,7 +84,7 @@ public class CDAKGlobals { You can inject any custom code systems and OIDs here */ - public var CDAK_EXTENDED_CODE_SYSTEMS: [String:String] = CDAKCodeSystemHelper.CODE_SYSTEMS + open var CDAK_EXTENDED_CODE_SYSTEMS: [String:String] = CDAKCodeSystemHelper.CODE_SYSTEMS } diff --git a/CDAKit/health-data-standards/swift_helpers/CDAKJSONInstantiable.swift b/CDAKit/health-data-standards/swift_helpers/CDAKJSONInstantiable.swift index 1e21da0..4b1ba89 100644 --- a/CDAKit/health-data-standards/swift_helpers/CDAKJSONInstantiable.swift +++ b/CDAKit/health-data-standards/swift_helpers/CDAKJSONInstantiable.swift @@ -20,7 +20,7 @@ internal protocol CDAKJSONInstantiable { // individual classes will handle this, NOT a Ruby-like reflection mechanism extension CDAKJSONInstantiable { - func initFromEventList(event: [String:Any?]) { + func initFromEventList(_ event: [String:Any?]) { for (key, value) in event { CDAKUtility.setProperty(self, property: key, value: value) } diff --git a/CDAKit/health-data-standards/swift_helpers/CDAKUtility.swift b/CDAKit/health-data-standards/swift_helpers/CDAKUtility.swift index b9cee6e..4caef37 100644 --- a/CDAKit/health-data-standards/swift_helpers/CDAKUtility.swift +++ b/CDAKit/health-data-standards/swift_helpers/CDAKUtility.swift @@ -40,34 +40,34 @@ class CDAKUtility { "codes" ] - class func intValue(value: Any?) -> Int? { + class func intValue(_ value: Any?) -> Int? { if let value = value as? Int { return value } else if let value = value as? Int? { return value } else if let value = value as? String { return Int(value) } - else if let value = value as? String?, u_value = value { return Int(u_value) } + else if let value = value as? String?, let u_value = value { return Int(u_value) } return nil } - class func doubleValue(value: Any?) -> Double? { + class func doubleValue(_ value: Any?) -> Double? { if let value = value as? Double { return value } else if let value = value as? Double? { return value } else if let value = value as? String { return Double(value) } - else if let value = value as? String?, u_value = value { return Double(u_value) } + else if let value = value as? String?, let u_value = value { return Double(u_value) } return nil } - class func stringValue(value: Any?) -> String? { + class func stringValue(_ value: Any?) -> String? { var a_value: String? if let value = value as? String { a_value = value } else if let value = value as? String? { a_value = value } - else if let value = value { a_value = String(value) } + else if let value = value { a_value = String(describing: value) } if let a_value = a_value { if a_value != "" { return a_value } } return nil } - class func boolValue(value: Any?) -> Bool? { + class func boolValue(_ value: Any?) -> Bool? { if let value = value as? Bool { return value } else if let value = value as? Bool? { return value } return nil @@ -78,14 +78,14 @@ class CDAKUtility { // BUT the code system might not be supplied // race {code: 12345 } // so we need to account for a flattened setup and the possibility of an absent code system - class func singleCodeFieldFlat(value: Any?, withDefaultCodeSystem defaultCodeSystem: String? = nil) -> CDAKCodedEntries { + class func singleCodeFieldFlat(_ value: Any?, withDefaultCodeSystem defaultCodeSystem: String? = nil) -> CDAKCodedEntries { var result: CDAKCodedEntries = CDAKCodedEntries() //print(value) print("singleCodeFieldFlat:value = \(value)") if let value = value as? [String:Any?] { if let val = value["code"] { if let val = val { //still optional - let code = String(val) //since we can have integers, etc. in here + let code = String(describing: val) //since we can have integers, etc. in here if code != "" { //filter out the weird "" we see in CDAK entries var codeSystem: String? if let val = value["codeSystem"] as? String { @@ -110,7 +110,7 @@ class CDAKUtility { //"codes" : ["CPT" : ["1234"]] //I feel so very very dirty. And yes - I realize how bad this code is. - class func dictionaryStringArray(value: Any?, withDefaultCodeSystem defaultCodeSystem: String? = nil) -> CDAKCodedEntries { + class func dictionaryStringArray(_ value: Any?, withDefaultCodeSystem defaultCodeSystem: String? = nil) -> CDAKCodedEntries { var result: CDAKCodedEntries = CDAKCodedEntries() print("dictionaryStringArray:value = \(value)") if let value = value as? CDAKCodedEntries { return value } @@ -141,7 +141,7 @@ class CDAKUtility { //print(value) if let values = value as? [Any?] { for code in values { - if let code = code as? String where code != "" { + if let code = code as? String , code != "" { result.addCodes(key, code: code) } } @@ -149,7 +149,7 @@ class CDAKUtility { } else if let values = value as? [Any] { //result.addCodes(key, codes: values.map({String($0)}).filter({$0 != ""})) for code in values { - if let code = code as? String where code != "" { + if let code = code as? String , code != "" { result.addCodes(key, code: code) } } @@ -165,13 +165,13 @@ class CDAKUtility { return result } - class func arrayOfCodedEntries(value: Any?) -> [CDAKCodedEntries] { + class func arrayOfCodedEntries(_ value: Any?) -> [CDAKCodedEntries] { var result: [CDAKCodedEntries] = [] //print(value) if let value = value as? [Any] { for value in value { - if let value = value as? [String:Any?], codes = value["codes"] { + if let value = value as? [String:Any?], let codes = value["codes"] { let a_value = dictionaryStringArray(codes) if a_value.count > 0 { result.append(a_value) @@ -184,7 +184,7 @@ class CDAKUtility { } - class func dictionaryAny(value: Any?) -> [String:Any?] { + class func dictionaryAny(_ value: Any?) -> [String:Any?] { let result: [String:Any?] = [:] //print(value) if let value = value as? [String:Any?] { @@ -195,13 +195,13 @@ class CDAKUtility { } - class func debug_message(object: String, function: String, property: String) { + class func debug_message(_ object: String, function: String, property: String) { if CDAKUtility.DEBUG { if !CDAKUtility.entry_fields.contains(property) { print("\(function) for \(object) failed to return '\(property)' ") } } } - class func getProperty(obj: Any?, property: String) -> Any? { + class func getProperty(_ obj: Any?, property: String) -> Any? { if let obj = obj as? CDAKEntry { @@ -301,7 +301,7 @@ class CDAKUtility { return nil } - class func setProperty(obj: Any?, property: String, value: Any?) { + class func setProperty(_ obj: Any?, property: String, value: Any?) { if let obj = obj as? CDAKEntry { switch property { @@ -334,7 +334,7 @@ class CDAKUtility { units = stringValue(a_unit) } var scalar: String? - if let a_scalar = event["scalar"], another_scalar = stringValue(a_scalar) { + if let a_scalar = event["scalar"], let another_scalar = stringValue(a_scalar) { //I know, I know - we're cleaning up weirdness in CDAK with "null" scalar = another_scalar } @@ -620,7 +620,7 @@ class CDAKUtility { //http://stackoverflow.com/questions/30897892/how-to-create-generic-convenience-initializer-in-swift //http://austinzheng.com/2015/09/29/swift-generics-pt-2/ //T.Type - class func createArrayOfEntries(type : T.Type, withValues value: Any?) -> [T] { + class func createArrayOfEntries(_ type : T.Type, withValues value: Any?) -> [T] { var result : [T] = [] if let values = value as? [Any] { for value in values { @@ -633,10 +633,10 @@ class CDAKUtility { } - class func convertStringToDictionary(text: String) -> [String:Any] { - if let data = text.dataUsingEncoding(NSUTF8StringEncoding) { + class func convertStringToDictionary(_ text: String) -> [String:Any] { + if let data = text.data(using: String.Encoding.utf8) { do { - let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? [String:AnyObject] + let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject] var otherJson: [String:Any] = [:] if let json = json { diff --git a/CDAKit/health-data-standards/swift_helpers/CDAKValueAndUnit.swift b/CDAKit/health-data-standards/swift_helpers/CDAKValueAndUnit.swift index 2ca19db..368ff01 100644 --- a/CDAKit/health-data-standards/swift_helpers/CDAKValueAndUnit.swift +++ b/CDAKit/health-data-standards/swift_helpers/CDAKValueAndUnit.swift @@ -40,10 +40,10 @@ extension CDAKValueAndUnit: CDAKJSONExportable { var dict: [String: AnyObject] = [:] if let value = value { - dict["value"] = value + dict["value"] = value as AnyObject? } if let unit = unit { - dict["unit"] = unit + dict["unit"] = unit as AnyObject? } return dict diff --git a/CDAKit/health-data-standards/swift_helpers/Dictionary+Extensions.swift b/CDAKit/health-data-standards/swift_helpers/Dictionary+Extensions.swift index 4f63766..141c74d 100644 --- a/CDAKit/health-data-standards/swift_helpers/Dictionary+Extensions.swift +++ b/CDAKit/health-data-standards/swift_helpers/Dictionary+Extensions.swift @@ -11,7 +11,7 @@ import Foundation //http://stackoverflow.com/questions/26728477/swift-how-to-combine-two-dictionary-arrays //http://ericasadun.com/2015/07/08/swift-merging-dictionaries/ extension Dictionary { - mutating func merge(dict: [K: V]){ + mutating func merge(_ dict: [K: V]){ for (k, v) in dict { self.updateValue(v as! Value, forKey: k as! Key) } @@ -20,11 +20,11 @@ extension Dictionary { func inverse() -> [String:String] { var inverted : [String:String] = [:] for (key, value) in self { - if let value = value as? String, key = key as? String { + if let value = value as? String, let key = key as? String { inverted[value] = key } } return inverted } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/swift_helpers/Mustache+Filters.swift b/CDAKit/health-data-standards/swift_helpers/Mustache+Filters.swift index 47e132e..25f43fd 100644 --- a/CDAKit/health-data-standards/swift_helpers/Mustache+Filters.swift +++ b/CDAKit/health-data-standards/swift_helpers/Mustache+Filters.swift @@ -12,7 +12,7 @@ import Mustache class MustacheFilters { static let UUID_generate = Filter { (value: Any? ) in - let uuid_string = NSUUID().UUIDString + let uuid_string = NSUUID().uuidString return Box(uuid_string) } @@ -20,17 +20,17 @@ class MustacheFilters { static let DateAsNumber = Filter { (box: MustacheBox) in if box.value == nil { - return Box(NSDate().stringFormattedAsHDSDateNumber) + return Box(Date().stringFormattedAsHDSDateNumber) } switch box.value { case let int as Int: - let d = NSDate(timeIntervalSince1970: Double(int)) + let d = Date(timeIntervalSince1970: Double(int)) return Box(d.stringFormattedAsHDSDateNumber) case let double as Double: - let d = NSDate(timeIntervalSince1970: double) + let d = Date(timeIntervalSince1970: double) return Box(d.stringFormattedAsHDSDateNumber) - case let date as NSDate: + case let date as Date: return Box(date.stringFormattedAsHDSDateNumber) default: return Box() @@ -40,17 +40,17 @@ class MustacheFilters { static let DateAsHDSString = Filter { (box: MustacheBox) in if box.value == nil { - return Box(NSDate().stringFormattedAsHDSDate) + return Box(Date().stringFormattedAsHDSDate) } switch box.value { case let int as Int: - let d = NSDate(timeIntervalSince1970: Double(int)) + let d = Date(timeIntervalSince1970: Double(int)) return Box(d.stringFormattedAsHDSDate) case let double as Double: - let d = NSDate(timeIntervalSince1970: double) + let d = Date(timeIntervalSince1970: double) return Box(d.stringFormattedAsHDSDate) - case let date as NSDate: + case let date as Date: return Box(date.stringFormattedAsHDSDate) default: return Box() @@ -92,8 +92,7 @@ class MustacheFilters { case let val as Bool?: return Box(true) case let val as String: - //.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) - if val.lowercaseString == "true" || val.lowercaseString == "false" { + if val.lowercased() == "true" || val.lowercased() == "false" { return Box(true) } return Box(false) @@ -125,4 +124,4 @@ class MustacheFilters { } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/swift_helpers/NSDate+Formatters.swift b/CDAKit/health-data-standards/swift_helpers/NSDate+Formatters.swift index 4607367..51f4ff3 100644 --- a/CDAKit/health-data-standards/swift_helpers/NSDate+Formatters.swift +++ b/CDAKit/health-data-standards/swift_helpers/NSDate+Formatters.swift @@ -10,25 +10,25 @@ import Foundation -extension NSDate { +extension Date { var stringFormattedAsRFC3339: String { - return rfc3339formatter.stringFromDate(self) + return rfc3339formatter.string(from: self) } //http://stackoverflow.com/questions/24089999/how-do-you-create-a-swift-date-object //NSDate(dateString:"2014-06-06") //https://gist.github.com/algal/09b08515460b7bd229fa - class func dateFromRFC3339FormattedString(rfc3339FormattedString:String) -> NSDate? + static func dateFromRFC3339FormattedString(_ rfc3339FormattedString:String) -> Date? { /* NOTE: will replace this with a failible initializer when Apple fixes the bug that requires the initializer to initialize all stored properties before returning nil, even when this is impossible. */ - if let d = rfc3339formatter.dateFromString(rfc3339FormattedString) + if let d = rfc3339formatter.date(from: rfc3339FormattedString) { - return NSDate(timeInterval:0,sinceDate:d) + return Date(timeInterval:0,since:d) } else { return nil @@ -37,27 +37,27 @@ extension NSDate { var stringFormattedAsHDSDate: String { - return hdsDateformatter.stringFromDate(self).stringByReplacingOccurrencesOfString(",", withString: daySuffix(self)+",") + return hdsDateformatter.string(from: self).replacingOccurrences(of: ",", with: daySuffix(self)+",") } var stringFormattedAsHDSDateNumber: String { - return hdsDateNumberformatter.stringFromDate(self) + return hdsDateNumberformatter.string(from: self) } - class func dateFromHDSFormattedString(hdsFormattedString:String) -> NSDate? + static func dateFromHDSFormattedString(_ hdsFormattedString:String) -> Date? { //we're abusing the possible formats here // if we have "December 31, 2009" we're OK for date formatter // if we have "December 31st, 2009" then we have to rip out st, nd, rd, th day suffixes - if let d = hdsDateformatter.dateFromString(CDAKCommonUtility.Regex.replaceMatches("(\\d)(st|nd|rd|th)(,)", inString: hdsFormattedString, withString: "$1$3")!) + if let d = hdsDateformatter.date(from: CDAKCommonUtility.Regex.replaceMatches("(\\d)(st|nd|rd|th)(,)", inString: hdsFormattedString, withString: "$1$3")!) { - return NSDate(timeInterval:0,sinceDate:d) - } else if let d = hdsDateNumberformatter.dateFromString(hdsFormattedString) { - return NSDate(timeInterval: 0, sinceDate: d) - } else if let d = hdsDateNumberFormatterShort.dateFromString(hdsFormattedString) { - return NSDate(timeInterval: 0, sinceDate: d) - } else if let d = hdsDateNumberFormatterYearOnly.dateFromString(hdsFormattedString) { - return NSDate(timeInterval: 0, sinceDate: d) + return Date(timeInterval:0,since:d) + } else if let d = hdsDateNumberformatter.date(from: hdsFormattedString) { + return Date(timeInterval: 0, since: d) + } else if let d = hdsDateNumberFormatterShort.date(from: hdsFormattedString) { + return Date(timeInterval: 0, since: d) + } else if let d = hdsDateNumberFormatterYearOnly.date(from: hdsFormattedString) { + return Date(timeInterval: 0, since: d) } else { return nil @@ -66,11 +66,11 @@ extension NSDate { //http://stackoverflow.com/questions/7416865/date-formatter-for-converting-14-sept-2011-in-14th-sept //http://stackoverflow.com/questions/1283045/ordinal-month-day-suffix-option-for-nsdateformatter-setdateformat - func daySuffix(date: NSDate) -> String { + func daySuffix(_ date: Date) -> String { //let calendar = NSCalendar.currentCalendar() - let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! - calendar.timeZone = NSTimeZone(forSecondsFromGMT: 0) - let dayOfMonth = calendar.component(.Day, fromDate: date) + var calendar = Calendar(identifier: Calendar.Identifier.iso8601) + calendar.timeZone = TimeZone(secondsFromGMT: 0)! + let dayOfMonth = (calendar as NSCalendar).component(.day, from: date) switch dayOfMonth { case 1, 21, 31: return "st" case 2, 22: return "nd" @@ -83,55 +83,55 @@ extension NSDate { } -private var rfc3339formatter:NSDateFormatter = { - let formatter = NSDateFormatter() +private var rfc3339formatter:DateFormatter = { + let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z" - formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - formatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! - formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") return formatter }() // http://apidock.com/rails/ActiveSupport/CoreExtensions/DateTime/Conversions/to_formatted_s // datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00" // http://www.codingexplorer.com/swiftly-getting-human-readable-date-nsdateformatter/ -private var hdsDateformatter:NSDateFormatter = { - let formatter = NSDateFormatter() +private var hdsDateformatter:DateFormatter = { + let formatter = DateFormatter() formatter.dateFormat = "MMMM d, yyyy HH:mm" - formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - formatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! - formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") return formatter }() //20070118061017 //http://apidock.com/rails/Time/to_formatted_s -private var hdsDateNumberformatter:NSDateFormatter = { - let formatter = NSDateFormatter() +private var hdsDateNumberformatter:DateFormatter = { + let formatter = DateFormatter() formatter.dateFormat = "yyyyMMddHHmmss" - formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - formatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! - formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") return formatter }() //we've seen some files not following spec and failing to include HHmmss //200701180 -private var hdsDateNumberFormatterShort:NSDateFormatter = { - let formatter = NSDateFormatter() +private var hdsDateNumberFormatterShort:DateFormatter = { + let formatter = DateFormatter() formatter.dateFormat = "yyyyMMdd" - formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - formatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! - formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") return formatter }() //as well as just years.... social history with just "1947" //200701180 -private var hdsDateNumberFormatterYearOnly:NSDateFormatter = { - let formatter = NSDateFormatter() +private var hdsDateNumberFormatterYearOnly:DateFormatter = { + let formatter = DateFormatter() formatter.dateFormat = "yyyy" - formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - formatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! - formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") return formatter -}() \ No newline at end of file +}() diff --git a/CDAKit/health-data-standards/swift_helpers/NSObject+PropertyNames.swift b/CDAKit/health-data-standards/swift_helpers/NSObject+PropertyNames.swift index 88ed8c2..a22a84c 100644 --- a/CDAKit/health-data-standards/swift_helpers/NSObject+PropertyNames.swift +++ b/CDAKit/health-data-standards/swift_helpers/NSObject+PropertyNames.swift @@ -26,21 +26,21 @@ extension NSObject { let properties = class_copyPropertyList(myClass, &count); // iterate each objc_property_t struct - for var i: UInt32 = 0; i < count; i++ { - let property = properties[Int(i)]; + for i: UInt32 in 0 ..< count { + let property = properties?[Int(i)]; // retrieve the property name by calling property_getName function let cname = property_getName(property); // covert the c string into a Swift string - let name = String.fromCString(cname); - results.append(name!); + let name = String(cString: cname!); + results.append(name); } // release objc_property_t structs free(properties); - results.appendContentsOf(SwiftPropertyNames()) + results.append(contentsOf: SwiftPropertyNames()) results = Array(Set(results)) return results; @@ -52,4 +52,4 @@ extension NSObject { } -} \ No newline at end of file +} diff --git a/CDAKit/health-data-standards/swift_helpers/String+Extensions.swift b/CDAKit/health-data-standards/swift_helpers/String+Extensions.swift index 8a9fd0b..3f1a89e 100644 --- a/CDAKit/health-data-standards/swift_helpers/String+Extensions.swift +++ b/CDAKit/health-data-standards/swift_helpers/String+Extensions.swift @@ -13,7 +13,7 @@ extension String { //http://stackoverflow.com/questions/24092884/get-nth-character-of-a-string-in-swift-programming-language subscript (i: Int) -> Character { - return self[self.startIndex.advancedBy(i)] + return self[self.characters.index(self.startIndex, offsetBy: i)] } subscript (i: Int) -> String { @@ -21,9 +21,26 @@ extension String { } subscript (r: Range) -> String { - return substringWithRange(Range(start: startIndex.advancedBy(r.startIndex), end: startIndex.advancedBy(r.endIndex))) + return substring(with: (characters.index(startIndex, offsetBy: r.lowerBound) ..< characters.index(startIndex, offsetBy: r.upperBound))) } -} + func index(from: Int) -> Index { + return self.index(startIndex, offsetBy: from) + } + + func substring(from: Int) -> String { + let fromIndex = index(from: from) + return substring(from: fromIndex) + } + func substring(to: Int) -> String { + let toIndex = index(from: to) + return substring(to: toIndex) + } + func substring(with r: Range) -> String { + let startIndex = index(from: r.lowerBound) + let endIndex = index(from: r.upperBound) + return substring(with: startIndex.. CDAKProvider? { + func my_resolve_provider(_ provider_hash: [String:Any], patient: CDAKPerson? = nil) -> CDAKProvider? { return CDAKGlobals.sharedInstance.CDAKProviders.first } diff --git a/CDAKitTests/DateShiftTest.swift b/CDAKitTests/DateShiftTest.swift index b549cdf..7e9d490 100644 --- a/CDAKitTests/DateShiftTest.swift +++ b/CDAKitTests/DateShiftTest.swift @@ -284,7 +284,7 @@ class DateShiftTest: XCTestCase { //helper method for other tests //field_values appear to be things like ["start_time":1] or ["start_time":nil] - func entry_shift_assertions(field_values:[String:Any?], shift: Double, entry: CDAKPropertyAddressable, block: (()->())? = nil ) { + func entry_shift_assertions(_ field_values:[String:Any?], shift: Double, entry: CDAKPropertyAddressable, block: (()->())? = nil ) { for (field, value) in field_values { //get the value from the entry diff --git a/CDAKitTests/EntryTest.swift b/CDAKitTests/EntryTest.swift index e9b8c97..f855bb9 100644 --- a/CDAKitTests/EntryTest.swift +++ b/CDAKitTests/EntryTest.swift @@ -113,11 +113,11 @@ class EntryTest: XCTestCase { // print(String(hash["code"]!!)) // print(entry.codes[String(hash["code_set"]!!)]!) // XCTAssertEqual([String(hash["code"]!)], entry.codes[String(hash["code_set"]!!)]!) - XCTAssertEqual([String(hash["code"]!)], [entry.codes["RxNorm"]!.first!.code]) - XCTAssertEqual(String(hash["value"]!!), (entry.values.first as! CDAKPhysicalQuantityResultValue).scalar) - XCTAssertEqual(String(hash["unit"]!!), (entry.values.first as! CDAKPhysicalQuantityResultValue).units) - XCTAssertEqual(String(hash["specifics"]!!), entry.specifics) - XCTAssertEqual(String(hash["status"]!!), entry.status) + XCTAssertEqual([String(describing: hash["code"]!)], [entry.codes["RxNorm"]!.first!.code]) + XCTAssertEqual(String(describing: hash["value"]!!), (entry.values.first as! CDAKPhysicalQuantityResultValue).scalar) + XCTAssertEqual(String(describing: hash["unit"]!!), (entry.values.first as! CDAKPhysicalQuantityResultValue).units) + XCTAssertEqual(String(describing: hash["specifics"]!!), entry.specifics) + XCTAssertEqual(String(describing: hash["status"]!!), entry.status) } func test_unusable_without_time() { diff --git a/CDAKitTests/GRMustacheTest.swift b/CDAKitTests/GRMustacheTest.swift index 4bc1bf9..f08144e 100644 --- a/CDAKitTests/GRMustacheTest.swift +++ b/CDAKitTests/GRMustacheTest.swift @@ -15,10 +15,10 @@ class GRMustacheTest: XCTestCase { let data = [ "name": "Arthur", - "date": NSDate(), - "realDate": NSDate().dateByAddingTimeInterval(60*60*24*3), + "date": Date(), + "realDate": Date().addingTimeInterval(60*60*24*3), "late": true - ] + ] as [String : Any] override func setUp() { super.setUp() @@ -71,13 +71,13 @@ class GRMustacheTest: XCTestCase { func testFileWithFile() { do { - let bundle = NSBundle(forClass: self.dynamicType) - let path = bundle.pathForResource("document", ofType: "mustache") + let bundle = Bundle(for: type(of: self)) + let path = bundle.path(forResource: "document", ofType: "mustache") let template = try Template(path: path!) // Let template format dates with `{{format(...)}}` - let dateFormatter = NSDateFormatter() - dateFormatter.dateStyle = .MediumStyle + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .medium template.registerInBaseContext("format", Box(dateFormatter)) let rendering = try template.render(Box(data)) @@ -90,7 +90,7 @@ class GRMustacheTest: XCTestCase { func testFileWithURL() { do { - let templateURL = NSURL(fileURLWithPath: "document.mustache") + let templateURL = URL(fileURLWithPath: "document.mustache") let template = try Template(URL: templateURL) let rendering = try template.render(Box(data)) print(rendering) @@ -117,7 +117,7 @@ class GRMustacheTest: XCTestCase { // static let sharedInstance = UUIDGenerator() // } - public class UUIDGenerator: MustacheBoxable { + open class UUIDGenerator: MustacheBoxable { // required init?(coder aDecoder: NSCoder) { // //super.init(value: aDecoder) @@ -136,8 +136,8 @@ class GRMustacheTest: XCTestCase { // ) // } - public var mustacheBox: MustacheBox { - return Box(NSUUID().UUIDString) + open var mustacheBox: MustacheBox { + return Box(NSUUID().uuidString) } static let sharedInstance = UUIDGenerator() @@ -149,8 +149,8 @@ class GRMustacheTest: XCTestCase { //let uuid = NSUUID().UUIDString - let percentFormatter = NSNumberFormatter() - percentFormatter.numberStyle = .PercentStyle + let percentFormatter = NumberFormatter() + percentFormatter.numberStyle = .percent do { let template = try Template(string: "{{ percent(x) }}") @@ -196,7 +196,7 @@ class GRMustacheTest: XCTestCase { func testFilter() { let reverse = Filter { (rendering: Rendering) in - let reversedString = String(rendering.string.characters.reverse()) + let reversedString = String(rendering.string.characters.reversed()) return Rendering(reversedString, rendering.contentType) } @@ -234,24 +234,24 @@ class GRMustacheTest: XCTestCase { let DateAsNumber = Filter { (box: MustacheBox) in if box.value == nil { - return Box(NSDate().stringFormattedAsHDSDateNumber) + return Box(Date().stringFormattedAsHDSDateNumber) } switch box.value { case let int as Int: print("I'm an Int") - let d = NSDate(timeIntervalSince1970: Double(int)) + let d = Date(timeIntervalSince1970: Double(int)) return Box(d.stringFormattedAsHDSDateNumber) case let double as Double: print("I'm a double") - let d = NSDate(timeIntervalSince1970: double) + let d = Date(timeIntervalSince1970: double) return Box(d.stringFormattedAsHDSDateNumber) - case let date as NSDate: + case let date as Date: print("I'm a date") return Box(date.stringFormattedAsHDSDateNumber) default: // GRMustache does not support any other numeric types: give up. - print("I'm of type \(box.value.dynamicType)") + print("I'm of type \(type(of: box.value))") return Box() } } @@ -260,7 +260,7 @@ class GRMustacheTest: XCTestCase { do { let template = try Template(string: "Date: {{ date_as_number(x) }}, Int: {{date_as_number(y)}} , Double: {{ date_as_number(z) }}, nil: {{ date_as_number(nil) }}") template.registerInBaseContext("date_as_number", Box(MustacheFilters.DateAsNumber)) - let data = ["x": NSDate(), "y":Int(NSDate().timeIntervalSince1970), "z":NSDate().timeIntervalSince1970] + let data = ["x": Date(), "y":Int(Date().timeIntervalSince1970), "z":Date().timeIntervalSince1970] as [String : Any] let rendering = try template.render(Box(data)) print(rendering) } @@ -286,10 +286,10 @@ class GRMustacheTest: XCTestCase { // return Box(result) // } - func convertStringToDictionary(text: String) -> [String:Any] { - if let data = text.dataUsingEncoding(NSUTF8StringEncoding) { + func convertStringToDictionary(_ text: String) -> [String:Any] { + if let data = text.data(using: String.Encoding.utf8) { do { - let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? [String:AnyObject] + let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject] var otherJson: [String:Any] = [:] if let json = json { @@ -459,8 +459,8 @@ class GRMustacheTest: XCTestCase { // disables all HTML escaping // Mustache.DefaultConfiguration.contentType = .Text - let bundle = NSBundle(forClass: self.dynamicType) - let path = bundle.pathForResource("record", ofType: "mustache") + let bundle = Bundle(for: type(of: self)) + let path = bundle.path(forResource: "record", ofType: "mustache") let template = try Template(path: path!) let data = ["patient": bigTestRecord] @@ -551,7 +551,7 @@ class GRMustacheTest: XCTestCase { // // } - func transformAnyObjectDict(dict: [String:AnyObject]) -> [String:Any?] { + func transformAnyObjectDict(_ dict: [String:AnyObject]) -> [String:Any?] { var otherJson: [String:Any?] = [:] for(key, value) in dict { if let value = value as? [String:AnyObject] { @@ -642,19 +642,19 @@ class GRMustacheTest: XCTestCase { // // } - func loadJSONFromBundleFile(filename: String) -> [String:AnyObject]? { + func loadJSONFromBundleFile(_ filename: String) -> [String:AnyObject]? { let fileName = "\(filename)" let directory: String? = nil - let bundle = NSBundle(forClass: self.dynamicType) + let bundle = Bundle(for: type(of: self)) //NSBundle.mainBundle() - guard let filePath = bundle.pathForResource(fileName, ofType: "json", inDirectory: directory) else { + guard let filePath = bundle.path(forResource: fileName, ofType: "json", inDirectory: directory) else { fatalError("Failed to find file '\(fileName)' in path '\(directory)' ") } - let templateURL = NSURL(fileURLWithPath: filePath) - if let data = NSData(contentsOfURL: templateURL) { + let templateURL = URL(fileURLWithPath: filePath) + if let data = try? Data(contentsOf: templateURL) { return convertDataToDictionary(data) } return nil @@ -662,8 +662,8 @@ class GRMustacheTest: XCTestCase { //http://stackoverflow.com/questions/30480672/how-to-convert-a-json-string-to-a-dictionary - func convertStringToDictionary(text: String) -> [String:AnyObject]? { - if let data = text.dataUsingEncoding(NSUTF8StringEncoding) { + func convertStringToDictionary(_ text: String) -> [String:AnyObject]? { + if let data = text.data(using: String.Encoding.utf8) { // do { // let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? [String:AnyObject] // return json @@ -676,9 +676,9 @@ class GRMustacheTest: XCTestCase { return nil } - func convertDataToDictionary(data: NSData) -> [String:AnyObject]? { + func convertDataToDictionary(_ data: Data) -> [String:AnyObject]? { do { - let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? [String:AnyObject] + let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject] return json } catch let error as NSError { diff --git a/CDAKitTests/HL7HelperTest.swift b/CDAKitTests/HL7HelperTest.swift index 173bc80..bf024e1 100644 --- a/CDAKitTests/HL7HelperTest.swift +++ b/CDAKitTests/HL7HelperTest.swift @@ -27,12 +27,12 @@ class HL7HelperTest: XCTestCase { let ts = CDAKHL7Helper.timestamp_to_integer(dateString) - let dateStringFormatter = NSDateFormatter() + let dateStringFormatter = DateFormatter() dateStringFormatter.dateFormat = "yyyyMMdd" - dateStringFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - dateStringFormatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! - dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") - let d = dateStringFormatter.dateFromString(dateString)! + dateStringFormatter.timeZone = TimeZone(secondsFromGMT: 0) + dateStringFormatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601) + dateStringFormatter.locale = Locale(identifier: "en_US_POSIX") + let d = dateStringFormatter.date(from: dateString)! XCTAssertEqual(d.timeIntervalSince1970, ts) } @@ -46,12 +46,12 @@ class HL7HelperTest: XCTestCase { let ts = CDAKHL7Helper.timestamp_to_integer(dateString) - let dateStringFormatter = NSDateFormatter() + let dateStringFormatter = DateFormatter() dateStringFormatter.dateFormat = "yyyyMM" - dateStringFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - dateStringFormatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! - dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") - let d = dateStringFormatter.dateFromString(dateString)! + dateStringFormatter.timeZone = TimeZone(secondsFromGMT: 0) + dateStringFormatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601) + dateStringFormatter.locale = Locale(identifier: "en_US_POSIX") + let d = dateStringFormatter.date(from: dateString)! XCTAssertEqual(d.timeIntervalSince1970, ts) } @@ -61,12 +61,12 @@ class HL7HelperTest: XCTestCase { let ts = CDAKHL7Helper.timestamp_to_integer(dateString) - let dateStringFormatter = NSDateFormatter() + let dateStringFormatter = DateFormatter() dateStringFormatter.dateFormat = "yyyyMMddHHmmss" - dateStringFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - dateStringFormatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)! - dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") - let d = dateStringFormatter.dateFromString(dateString)! + dateStringFormatter.timeZone = TimeZone(secondsFromGMT: 0) + dateStringFormatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601) + dateStringFormatter.locale = Locale(identifier: "en_US_POSIX") + let d = dateStringFormatter.date(from: dateString)! XCTAssertEqual(d.timeIntervalSince1970, ts) diff --git a/CDAKitTests/HealthKitRecordTest.swift b/CDAKitTests/HealthKitRecordTest.swift index 3cf57a2..5590b90 100644 --- a/CDAKitTests/HealthKitRecordTest.swift +++ b/CDAKitTests/HealthKitRecordTest.swift @@ -38,8 +38,8 @@ class HealthKitRecordTest: XCTestCase { let aVital = CDAKVitalSign() aVital.codes.addCodes("LOINC", code: "3141-9", displayName: "weight") //weight aVital.values.append(CDAKPhysicalQuantityResultValue(scalar: 155.0, units: "lb")) - aVital.start_time = NSDate().timeIntervalSince1970 - aVital.end_time = NSDate().timeIntervalSince1970 + aVital.start_time = Date().timeIntervalSince1970 + aVital.end_time = Date().timeIntervalSince1970 //append our height to our record record.vital_signs.append(aVital) @@ -78,8 +78,8 @@ class HealthKitRecordTest: XCTestCase { let aVital = CDAKVitalSign() aVital.codes.addCodes("LOINC", code: "3141-9", displayName: "Weight") //weight aVital.values.append(CDAKPhysicalQuantityResultValue(scalar: 155.0, units: "lb")) - aVital.start_time = NSDate().timeIntervalSince1970 - aVital.end_time = NSDate().timeIntervalSince1970 + aVital.start_time = Date().timeIntervalSince1970 + aVital.end_time = Date().timeIntervalSince1970 //let xmlString = aRecord.export(inFormat: .ccda) //print(xmlString) @@ -89,10 +89,10 @@ class HealthKitRecordTest: XCTestCase { XCTAssertEqual(hkRecord.samples.count, aRecord.vital_signs.count) //HKQuantityTypeIdentifierHeight - let aUnit = HKUnit(fromString: "in") + let aUnit = HKUnit(from: "in") let aQty = HKQuantity(unit: aUnit, doubleValue: 72 ) - let aQtyType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight) - let hkHeight = HKQuantitySample(type: aQtyType!, quantity: aQty, startDate: NSDate(), endDate: NSDate()) + let aQtyType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height) + let hkHeight = HKQuantitySample(type: aQtyType!, quantity: aQty, start: Date(), end: Date()) hkRecord.samples.append(hkHeight) //print(hkRecord) @@ -122,9 +122,9 @@ class HealthKitRecordTest: XCTestCase { func testSampleTypes() { let bmi: Double = 24.1 - let bmiType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMassIndex) - let bmiQuantity = HKQuantity(unit: HKUnit.countUnit(), doubleValue: bmi) - let bmiSample = HKQuantitySample(type: bmiType!, quantity: bmiQuantity, startDate: NSDate(), endDate: NSDate()) + let bmiType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMassIndex) + let bmiQuantity = HKQuantity(unit: HKUnit.count(), doubleValue: bmi) + let bmiSample = HKQuantitySample(type: bmiType!, quantity: bmiQuantity, start: Date(), end: Date()) print(bmiSample) } @@ -224,7 +224,7 @@ class HealthKitRecordTest: XCTestCase { let hds_hr = CDAKPhysicalQuantityResultValue(scalar: 86, units: hr_unit) // and we can build a HealthKit version - let hk_hr: HKQuantity = HKQuantity(unit: HKUnit(fromString: hr_unit), doubleValue: hr_value) + let hk_hr: HKQuantity = HKQuantity(unit: HKUnit(from: hr_unit), doubleValue: hr_value) @@ -266,7 +266,7 @@ class HealthKitRecordTest: XCTestCase { func testCustomBridgeCDAStringFinder() { //var cdaStringUnitFinder : ((unit_string: String?, typeIdentifier: String? ) -> HKUnit?)? - var cdaStringUnitFinder_nil : ((unit_string: String?, typeIdentifier: String? ) -> HKUnit?) = { + var cdaStringUnitFinder_nil : ((_ unit_string: String?, _ typeIdentifier: String? ) -> HKUnit?) = { (unit_string: String?, typeIdentifier: String?) -> HKUnit? in return nil @@ -284,11 +284,11 @@ class HealthKitRecordTest: XCTestCase { XCTAssertNil(hk_hrEntry_nil) - var cdaStringUnitFinder : ((unit_string: String?, typeIdentifier: String? ) -> HKUnit?) = { + var cdaStringUnitFinder : ((_ unit_string: String?, _ typeIdentifier: String? ) -> HKUnit?) = { (unit_string: String?, typeIdentifier: String?) -> HKUnit? in if unit_string == "beats" { - return HKUnit(fromString: "count/min") + return HKUnit(from: "count/min") } return nil diff --git a/CDAKitTests/RecordTestElements.swift b/CDAKitTests/RecordTestElements.swift index 65113aa..ef51caa 100644 --- a/CDAKitTests/RecordTestElements.swift +++ b/CDAKitTests/RecordTestElements.swift @@ -21,7 +21,7 @@ class TestRecord { // return test_record_sequence // } - func allergy(sequence: Int = 1) -> CDAKAllergy { + func allergy(_ sequence: Int = 1) -> CDAKAllergy { let _allergy = CDAKAllergy() _allergy.codes = CDAKCodedEntries(codeSystem: "RxNorm", code: "70618") _allergy.start_time = 1264529050 @@ -36,7 +36,7 @@ class TestRecord { return _allergy } - func condition(sequence: Int = 1) -> CDAKCondition { + func condition(_ sequence: Int = 1) -> CDAKCondition { let _condition = CDAKCondition() _condition.codes = CDAKCodedEntries(codeSystem: "SNOMED-CT", code: "16356006") _condition.cause_of_death = false @@ -48,7 +48,7 @@ class TestRecord { return _condition } - func encounter(sequence: Int = 1) -> CDAKEncounter { + func encounter(_ sequence: Int = 1) -> CDAKEncounter { let _encounter = CDAKEncounter() _encounter.codes = CDAKCodedEntries(codeSystem: "CPT", code: "16356006") _encounter.start_time = 1267322332 @@ -64,7 +64,7 @@ class TestRecord { return _encounter } - func entry(sequence: Int = 1) -> CDAKEntry { + func entry(_ sequence: Int = 1) -> CDAKEntry { let _entry = CDAKEntry() _entry.codes = CDAKCodedEntries(codeSystem: "CPT", code: "99201") _entry.start_time = 1267322332 @@ -72,7 +72,7 @@ class TestRecord { return _entry } - func medical_equipment(sequence: Int = 1) -> CDAKMedicalEquipment { + func medical_equipment(_ sequence: Int = 1) -> CDAKMedicalEquipment { let _medical_equipment = CDAKMedicalEquipment() _medical_equipment.codes = CDAKCodedEntries(codeSystem: "SNOMED-CT", code: "598721") _medical_equipment.start_time = 1267322332 @@ -82,7 +82,7 @@ class TestRecord { return _medical_equipment } - func support(sequence: Int = 1) -> CDAKSupport { + func support(_ sequence: Int = 1) -> CDAKSupport { let _support = CDAKSupport() _support.given_name = "Bob" _support.family_name = "Loblaw" @@ -93,7 +93,7 @@ class TestRecord { return _support } - func orderInformation(sequence: Int = 1) -> CDAKOrderInformation { + func orderInformation(_ sequence: Int = 1) -> CDAKOrderInformation { let _orderInformation = CDAKOrderInformation() _orderInformation.order_number = "5" _orderInformation.fills = 4 @@ -104,7 +104,7 @@ class TestRecord { return _orderInformation } - func fulfillment_history(sequence: Int = 1) -> CDAKFulfillmentHistory { + func fulfillment_history(_ sequence: Int = 1) -> CDAKFulfillmentHistory { let _fulfillment_history = CDAKFulfillmentHistory() _fulfillment_history.prescription_number = "B324" _fulfillment_history.dispense_date = 1267332349 @@ -115,13 +115,13 @@ class TestRecord { return _fulfillment_history } - func organization(sequence: Int = 1) -> CDAKOrganization { + func organization(_ sequence: Int = 1) -> CDAKOrganization { let _organization = CDAKOrganization() _organization.name = "Doctor Worm & Associates" return _organization } - func address(sequence: Int = 1) -> CDAKAddress { + func address(_ sequence: Int = 1) -> CDAKAddress { let _address = CDAKAddress() _address.street = ["\(sequence) Sesame Street", "Apt \(sequence)"] _address.city = "Bedford" @@ -130,7 +130,7 @@ class TestRecord { return _address } - func telecom(sequence: Int = 1) -> CDAKTelecom { + func telecom(_ sequence: Int = 1) -> CDAKTelecom { let _telecom = CDAKTelecom() _telecom.value = String(18005555555 + sequence) _telecom.use = ["fax", "phone", "mobile"].randomItem() @@ -139,7 +139,7 @@ class TestRecord { } //is this not supposed to be of type "CDAKEntry" ? Maybe "CDAKCondition" ? - func social_history(sequence: Int = 1) -> CDAKEntry { + func social_history(_ sequence: Int = 1) -> CDAKEntry { let _social_history = CDAKEntry() //_social_history.type = ["SNOMED-CT": ["398705004"]] //ok, this doesn't appear to be anywhere //the code does seem to state pretty clearly that this is an "CDAKEntry" @@ -149,24 +149,24 @@ class TestRecord { return _social_history } - func advance_directive(sequence: Int = 1) -> CDAKEntry { + func advance_directive(_ sequence: Int = 1) -> CDAKEntry { let _advance_directive = CDAKEntry() _advance_directive.codes = CDAKCodedEntries(codeSystem: "SNOMED-CT", code: "4234322") - let components: NSDateComponents = NSDateComponents() - components.setValue(-1, forComponent: NSCalendarUnit.Month) - let date: NSDate = NSDate() - let newDate = NSCalendar.currentCalendar().dateByAddingComponents(components, toDate: date, options: NSCalendarOptions(rawValue: 0)) - let month_ago = NSNumber(double: (newDate!.timeIntervalSince1970)).doubleValue + let components: DateComponents = DateComponents() + (components as NSDateComponents).setValue(-1, forComponent: NSCalendar.Unit.month) + let date: Date = Date() + let newDate = (Calendar.current as NSCalendar).date(byAdding: components, to: date, options: NSCalendar.Options(rawValue: 0)) + let month_ago = NSNumber(value: (newDate!.timeIntervalSince1970) as Double).doubleValue _advance_directive.start_time = month_ago - _advance_directive.end_time = NSNumber(double: (NSDate().timeIntervalSince1970)).doubleValue + _advance_directive.end_time = NSNumber(value: (Date().timeIntervalSince1970)).doubleValue _advance_directive.item_description = "Go insane" return _advance_directive } - func immunization(sequence: Int = 1) -> CDAKImmunization { + func immunization(_ sequence: Int = 1) -> CDAKImmunization { let _immunization = CDAKImmunization() _immunization.codes = CDAKCodedEntries(codeSystem: "RxNorm", code: "854931") _immunization.time = 1264529050 @@ -178,13 +178,13 @@ class TestRecord { return _immunization } - func lab_result(sequence: Int = 1) -> CDAKLabResult { + func lab_result(_ sequence: Int = 1) -> CDAKLabResult { let _lab_result = CDAKLabResult() return _lab_result } - func medication(sequence: Int = 1) -> CDAKMedication { + func medication(_ sequence: Int = 1) -> CDAKMedication { let _medication = CDAKMedication() _medication.codes = CDAKCodedEntries(codeSystem: "RxNorm", code: "105075") _medication.item_description = "Tobacco Cessation Agent" @@ -231,7 +231,7 @@ class TestRecord { return _medication } - func order_information(sequence: Int = 1) -> CDAKOrderInformation { + func order_information(_ sequence: Int = 1) -> CDAKOrderInformation { let _order_information = CDAKOrderInformation() return _order_information } @@ -241,7 +241,7 @@ class TestRecord { return _physical_quantity_result_value } - func procedure(sequence: Int = 1) -> CDAKProcedure { + func procedure(_ sequence: Int = 1) -> CDAKProcedure { let _procedure = CDAKProcedure() _procedure.codes = CDAKCodedEntries(codeSystem: "SNOMED-CT", code: "171055003") _procedure.start_time = 1257901150 @@ -251,14 +251,14 @@ class TestRecord { return _procedure } - func record(sequence: Int = 1) -> CDAKRecord { + func record(_ sequence: Int = 1) -> CDAKRecord { let _record = CDAKRecord() _record.encounters = [encounter()] return _record } - func bigger_record(sequence: Int = 1) -> CDAKRecord { + func bigger_record(_ sequence: Int = 1) -> CDAKRecord { let _bigger_record = CDAKRecord() for x in 1...3 { _bigger_record.encounters.append(encounter(x)) @@ -270,7 +270,7 @@ class TestRecord { return _bigger_record } - func vital_sign(sequence: Int = 1) -> CDAKVitalSign { + func vital_sign(_ sequence: Int = 1) -> CDAKVitalSign { let _vital_sign = CDAKVitalSign() _vital_sign.codes = CDAKCodedEntries(codeSystem: "SNOMED-CT", code: "225171007") _vital_sign.time = 1266664414 @@ -318,4 +318,4 @@ class TestRecord { } */ -} \ No newline at end of file +} diff --git a/CDAKitTests/TestHelpers.swift b/CDAKitTests/TestHelpers.swift index 8513a25..c84307e 100644 --- a/CDAKitTests/TestHelpers.swift +++ b/CDAKitTests/TestHelpers.swift @@ -70,14 +70,14 @@ class TestHelpers { class fileHelpers { - class func load_xml_data_from_file(filename: String) -> NSData + class func load_xml_data_from_file(_ filename: String) -> Data { - let bundle = NSBundle(forClass: TestHelpers.self) + let bundle = Bundle(for: TestHelpers.self) - let filepath = bundle.pathForResource(filename, ofType: "xml") + let filepath = bundle.path(forResource: filename, ofType: "xml") if let filepath = filepath { - if let data = NSData(contentsOfURL: NSURL(fileURLWithPath: filepath)) + if let data = try? Data(contentsOf: URL(fileURLWithPath: filepath)) { return data } @@ -92,11 +92,11 @@ class TestHelpers { } } - class func load_xml_string_from_file(filename: String) -> String + class func load_xml_string_from_file(_ filename: String) -> String { let data = load_xml_data_from_file(filename) - if let xml = NSString(data: data, encoding: NSUTF8StringEncoding) as? String + if let xml = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as? String { return xml } @@ -108,4 +108,4 @@ class TestHelpers { } -} \ No newline at end of file +} diff --git a/CDAKitTests/ViewHelperTest.swift b/CDAKitTests/ViewHelperTest.swift index 2d780ef..b3e11b6 100644 --- a/CDAKitTests/ViewHelperTest.swift +++ b/CDAKitTests/ViewHelperTest.swift @@ -34,8 +34,8 @@ class ViewHelperTest: XCTestCase { let code_xml = ViewHelper.code_display(entry) print("code_xml = \n\n\(code_xml)\n\n") - XCTAssert(!code_xml.containsString("bacon > cheese")) - XCTAssert(code_xml.containsString("bacon > cheese")) + XCTAssert(!(code_xml.range(of:"bacon > cheese") != nil)) + XCTAssert((code_xml.range(of: "bacon > cheese") != nil)) //Original test case. Changing the test case because I want to have codeSystemName in entries //XCTAssertEqual(code_xml, "bacon > cheese\n") XCTAssertEqual(code_xml, "bacon > cheese\n") @@ -47,9 +47,9 @@ class ViewHelperTest: XCTestCase { XCTAssertNil(ViewHelper.time_if_not_nil(nil, nil)) XCTAssertNotNil(ViewHelper.time_if_not_nil(nil, 7)) XCTAssertNotNil(ViewHelper.time_if_not_nil(7)) - XCTAssertEqual(NSDate(timeIntervalSince1970: 7), ViewHelper.time_if_not_nil(nil, 7)) - XCTAssertEqual(NSDate(timeIntervalSince1970: 7), ViewHelper.time_if_not_nil(7)) - XCTAssertEqual(NSDate(timeIntervalSince1970: 7), ViewHelper.time_if_not_nil(7, 8)) + XCTAssertEqual(Date(timeIntervalSince1970: 7), ViewHelper.time_if_not_nil(nil, 7)) + XCTAssertEqual(Date(timeIntervalSince1970: 7), ViewHelper.time_if_not_nil(7)) + XCTAssertEqual(Date(timeIntervalSince1970: 7), ViewHelper.time_if_not_nil(7, 8)) } } diff --git a/Podfile b/Podfile index f31cd32..73615c6 100644 --- a/Podfile +++ b/Podfile @@ -3,18 +3,14 @@ source 'https://github.com/CocoaPods/Specs.git' use_frameworks! target 'CDAKit' do - pod 'GRMustache.swift', '0.11.0' - pod 'Fuzi', '~> 0.3.0' - pod 'Try', '~> 1.0.0' - #pod 'SwiftTryCatch', :git => 'https://github.com/ravero/SwiftTryCatch.git' - #pod 'CryptoSwift' + pod 'GRMustache.swift', :git => 'https://github.com/groue/GRMustache.swift.git', :branch => 'Swift3' + pod 'Fuzi' + pod 'Try' end target 'CDAKitTests' do - pod 'GRMustache.swift', '0.11.0' - pod 'Fuzi', '~> 0.3.0' - pod 'Try', '~> 1.0.0' - #pod 'SwiftTryCatch', :git => 'https://github.com/ravero/SwiftTryCatch.git' - #pod 'CryptoSwift' + pod 'GRMustache.swift', :git => 'https://github.com/groue/GRMustache.swift.git', :branch => 'Swift3' + pod 'Fuzi' + pod 'Try' end From deac7d6d8b487237a6a3b5a59d02b847bae51d45 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Mon, 24 Oct 2016 10:26:31 -0400 Subject: [PATCH 02/15] Updating CDAKit.podspec to at least include needed updates to external pod references. --- CDAKit.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CDAKit.podspec b/CDAKit.podspec index b4d06e9..dc75dd9 100755 --- a/CDAKit.podspec +++ b/CDAKit.podspec @@ -31,7 +31,7 @@ Pod::Spec.new do |s| ] } s.frameworks = 'HealthKit' - s.dependency 'GRMustache.swift', '~> 0.11.0' - s.dependency 'Fuzi', '0.3.0' - s.dependency 'Try', '~> 1.0.0' + s.dependency 'GRMustache.swift', :git => 'https://github.com/groue/GRMustache.swift.git', :branch => 'Swift3' + s.dependency 'Fuzi' + s.dependency 'Try' end From 0fe7cbb7ee53b194303b083c28fcc804e94a7848 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Mon, 24 Oct 2016 13:32:14 -0400 Subject: [PATCH 03/15] Updated pod reference for GRMustache.swift to 2.0.0 as its now finally updated to Swift 3! Updated CDAKit.podspec and Podfile --- CDAKit.podspec | 6 +-- CDAKit.xcodeproj/project.pbxproj | 2 +- .../lib/export/HDSExport.swift | 16 +++---- .../lib/models/telecom.swift | 13 +++-- .../swift_helpers/Mustache+Filters.swift | 6 +-- CDAKitTests/GRMustacheTest.swift | 48 +++++++++---------- Podfile | 12 ++--- 7 files changed, 53 insertions(+), 50 deletions(-) diff --git a/CDAKit.podspec b/CDAKit.podspec index dc75dd9..c94054a 100755 --- a/CDAKit.podspec +++ b/CDAKit.podspec @@ -31,7 +31,7 @@ Pod::Spec.new do |s| ] } s.frameworks = 'HealthKit' - s.dependency 'GRMustache.swift', :git => 'https://github.com/groue/GRMustache.swift.git', :branch => 'Swift3' - s.dependency 'Fuzi' - s.dependency 'Try' + s.dependency 'GRMustache.swift', '~> 2.0.0' + s.dependency 'Fuzi', '~> 1.0.0' + s.dependency 'Try', '~> 1.0.0' end diff --git a/CDAKit.xcodeproj/project.pbxproj b/CDAKit.xcodeproj/project.pbxproj index 212b4bb..8aa6a89 100644 --- a/CDAKit.xcodeproj/project.pbxproj +++ b/CDAKit.xcodeproj/project.pbxproj @@ -1392,7 +1392,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Eric Whitley"; TargetAttributes = { 389170301C6CC1EE00A31299 = { diff --git a/CDAKit/health-data-standards/lib/export/HDSExport.swift b/CDAKit/health-data-standards/lib/export/HDSExport.swift index 11fc31a..1dbdc3c 100644 --- a/CDAKit/health-data-standards/lib/export/HDSExport.swift +++ b/CDAKit/health-data-standards/lib/export/HDSExport.swift @@ -45,18 +45,18 @@ open class CDAKExport { // we need to register our Mustache helpers //--------- // USE: telecoms:{{#each(patient.telecoms)}} hi {{value}} {{use}} {{/}} - template.registerInBaseContext("each", Box(StandardLibrary.each)) + template.register(Box(StandardLibrary.each), forKey: "each") // USE: {{ UUID_generate(nil) }} - template.registerInBaseContext("UUID_generate", Box(MustacheFilters.UUID_generate)) + template.register(Box(MustacheFilters.UUID_generate), forKey: "UUID_generate" ) // USE: {{ date_as_number(z) }}, nil: {{ date_as_number(nil) }} - template.registerInBaseContext("date_as_number", Box(MustacheFilters.DateAsNumber)) - template.registerInBaseContext("date_as_string", Box(MustacheFilters.DateAsHDSString)) + template.register(Box(MustacheFilters.DateAsNumber), forKey: "date_as_number" ) + template.register( Box(MustacheFilters.DateAsHDSString), forKey: "date_as_string") // USE: {{ value_or_null_flavor(entry.as_point_in_time) }} - template.registerInBaseContext("value_or_null_flavor", Box(MustacheFilters.value_or_null_flavor)) - template.registerInBaseContext("oid_for_code_system", Box(MustacheFilters.oid_for_code_system)) - template.registerInBaseContext("is_numeric", Box(MustacheFilters.is_numeric)) - template.registerInBaseContext("is_bool", Box(MustacheFilters.is_bool)) + template.register(Box(MustacheFilters.value_or_null_flavor), forKey:"value_or_null_flavor") + template.register(Box(MustacheFilters.oid_for_code_system), forKey: "oid_for_code_system") + template.register(Box(MustacheFilters.is_numeric), forKey:"is_numeric") + template.register(Box(MustacheFilters.is_bool), forKey: "is_bool") do { rendering = try template.render(Box(data)) diff --git a/CDAKit/health-data-standards/lib/models/telecom.swift b/CDAKit/health-data-standards/lib/models/telecom.swift index 5f3dcbe..2f34a8d 100644 --- a/CDAKit/health-data-standards/lib/models/telecom.swift +++ b/CDAKit/health-data-standards/lib/models/telecom.swift @@ -77,11 +77,14 @@ open class CDAKTelecom: NSObject, CDAKJSONInstantiable { extension CDAKTelecom { // MARK: - Mustache marshalling override open var mustacheBox: MustacheBox { - return Box([ - "use": use, - "value": value, - "preferred": String(describing: preferred) - ]) + let _value = self.value + let bb = [ + "use": self.use, + "value": _value, + "preferred": String(describing: self.preferred) + ] + + return Box(bb) } } diff --git a/CDAKit/health-data-standards/swift_helpers/Mustache+Filters.swift b/CDAKit/health-data-standards/swift_helpers/Mustache+Filters.swift index 25f43fd..67b5a96 100644 --- a/CDAKit/health-data-standards/swift_helpers/Mustache+Filters.swift +++ b/CDAKit/health-data-standards/swift_helpers/Mustache+Filters.swift @@ -33,7 +33,7 @@ class MustacheFilters { case let date as Date: return Box(date.stringFormattedAsHDSDateNumber) default: - return Box() + return nil } } @@ -53,7 +53,7 @@ class MustacheFilters { case let date as Date: return Box(date.stringFormattedAsHDSDate) default: - return Box() + return nil } } @@ -79,7 +79,7 @@ class MustacheFilters { let d = CDAKCodeSystemHelper.oid_for_code_system(code_system) return Box(d) default: - return Box() + return nil } } diff --git a/CDAKitTests/GRMustacheTest.swift b/CDAKitTests/GRMustacheTest.swift index f08144e..063d8b2 100644 --- a/CDAKitTests/GRMustacheTest.swift +++ b/CDAKitTests/GRMustacheTest.swift @@ -78,7 +78,7 @@ class GRMustacheTest: XCTestCase { // Let template format dates with `{{format(...)}}` let dateFormatter = DateFormatter() dateFormatter.dateStyle = .medium - template.registerInBaseContext("format", Box(dateFormatter)) + template.register(Box(dateFormatter), forKey:"format") let rendering = try template.render(Box(data)) print(rendering) @@ -154,7 +154,7 @@ class GRMustacheTest: XCTestCase { do { let template = try Template(string: "{{ percent(x) }}") - template.registerInBaseContext("percent", Box(percentFormatter)) + template.register(Box(percentFormatter), forKey: "percent") // Rendering: 50% let data = ["x": 0.5] @@ -163,7 +163,7 @@ class GRMustacheTest: XCTestCase { XCTAssertEqual(rendering, "50%") } catch { - + } } @@ -213,7 +213,7 @@ class GRMustacheTest: XCTestCase { let template = try Template(string: "{{ UUID_generate(nil) }}") - template.registerInBaseContext("UUID_generate", Box(MustacheFilters.UUID_generate)) + template.register(Box(MustacheFilters.UUID_generate), forKey: "UUID_generate") // Rendering: 50% let data = ["x": 0.5] @@ -252,14 +252,14 @@ class GRMustacheTest: XCTestCase { default: // GRMustache does not support any other numeric types: give up. print("I'm of type \(type(of: box.value))") - return Box() + return nil } } do { let template = try Template(string: "Date: {{ date_as_number(x) }}, Int: {{date_as_number(y)}} , Double: {{ date_as_number(z) }}, nil: {{ date_as_number(nil) }}") - template.registerInBaseContext("date_as_number", Box(MustacheFilters.DateAsNumber)) + template.register(Box(MustacheFilters.DateAsNumber), forKey: "date_as_number") let data = ["x": Date(), "y":Int(Date().timeIntervalSince1970), "z":Date().timeIntervalSince1970] as [String : Any] let rendering = try template.render(Box(data)) print(rendering) @@ -331,7 +331,7 @@ class GRMustacheTest: XCTestCase { do { let template = try Template(string: "code_display = {{# code_display(x)}}{\"tag_name\":\"value\",\"extra_content\":\"xsi:type=CD\",\"preferred_code_sets\":[\"SNOMED-CT\"]}{{/ }}") - template.registerInBaseContext("code_display", Box(code_display)) + template.register(Box(code_display), forKey: "code_display") let entry = CDAKEntry() entry.time = 1270598400 @@ -362,8 +362,8 @@ class GRMustacheTest: XCTestCase { let template = try Template(string: "time:{{entry.time}} codes:{{#each(entry.codes)}}{{@key}} {{#each(.)}} {{.}} {{/}} {{/}}") //each(entry.codes) let data = ["entry": entry] - template.registerInBaseContext("each", Box(StandardLibrary.each)) - let rendering = try template.render(Box(data)) + template.register(Box(StandardLibrary.each), forKey: "each") + let rendering = try template.render((data)) print("trying to render...") print(rendering) @@ -465,20 +465,20 @@ class GRMustacheTest: XCTestCase { let data = ["patient": bigTestRecord] // USE: telecoms:{{#each(patient.telecoms)}} hi {{value}} {{use}} {{/}} - template.registerInBaseContext("each", Box(StandardLibrary.each)) + template.register(Box(StandardLibrary.each), forKey: "each") // USE: {{ UUID_generate(nil) }} - template.registerInBaseContext("UUID_generate", Box(MustacheFilters.UUID_generate)) + template.register(Box(MustacheFilters.UUID_generate), forKey: "UUID_generate") // USE: {{ date_as_number(z) }}, nil: {{ date_as_number(nil) }} - template.registerInBaseContext("date_as_number", Box(MustacheFilters.DateAsNumber)) + template.register(Box(MustacheFilters.DateAsNumber), forKey: "date_as_number") // USE: {{ value_or_null_flavor(entry.as_point_in_time) }} - template.registerInBaseContext("value_or_null_flavor", Box(MustacheFilters.value_or_null_flavor)) + template.register(Box(MustacheFilters.value_or_null_flavor), forKey: "value_or_null_flavor") - template.registerInBaseContext("oid_for_code_system", Box(MustacheFilters.oid_for_code_system)) + template.register(Box(MustacheFilters.oid_for_code_system), forKey: "oid_for_code_system") - template.registerInBaseContext("is_numeric", Box(MustacheFilters.is_numeric)) - template.registerInBaseContext("is_bool", Box(MustacheFilters.is_bool)) + template.register(Box(MustacheFilters.is_numeric), forKey: "is_numeric") + template.register(Box(MustacheFilters.is_bool), forKey: "is_bool") //Removing this registration @@ -815,14 +815,14 @@ class GRMustacheTest: XCTestCase { let data = ["patient": record] - template.registerInBaseContext("each", Box(StandardLibrary.each)) - template.registerInBaseContext("UUID_generate", Box(MustacheFilters.UUID_generate)) - template.registerInBaseContext("date_as_number", Box(MustacheFilters.DateAsNumber)) - template.registerInBaseContext("date_as_string", Box(MustacheFilters.DateAsHDSString)) - template.registerInBaseContext("value_or_null_flavor", Box(MustacheFilters.value_or_null_flavor)) - template.registerInBaseContext("oid_for_code_system", Box(MustacheFilters.oid_for_code_system)) - template.registerInBaseContext("is_numeric", Box(MustacheFilters.is_numeric)) - template.registerInBaseContext("is_bool", Box(MustacheFilters.is_bool)) + template.register(Box(StandardLibrary.each), forKey: "each") + template.register(Box(MustacheFilters.UUID_generate), forKey: "UUID_generate") + template.register(Box(MustacheFilters.DateAsNumber), forKey: "date_as_number") + template.register(Box(MustacheFilters.DateAsHDSString), forKey: "date_as_string") + template.register(Box(MustacheFilters.value_or_null_flavor), forKey: "value_or_null_flavor") + template.register(Box(MustacheFilters.oid_for_code_system), forKey: "oid_for_code_system") + template.register(Box(MustacheFilters.is_numeric), forKey: "is_numeric") + template.register(Box(MustacheFilters.is_bool), forKey: "is_bool") do { diff --git a/Podfile b/Podfile index 73615c6..2c3a6d5 100644 --- a/Podfile +++ b/Podfile @@ -3,14 +3,14 @@ source 'https://github.com/CocoaPods/Specs.git' use_frameworks! target 'CDAKit' do - pod 'GRMustache.swift', :git => 'https://github.com/groue/GRMustache.swift.git', :branch => 'Swift3' - pod 'Fuzi' - pod 'Try' + pod 'GRMustache.swift', '~> 2.0.0' + pod 'Fuzi', '~> 1.0.0' + pod 'Try', '~> 1.0.0' end target 'CDAKitTests' do - pod 'GRMustache.swift', :git => 'https://github.com/groue/GRMustache.swift.git', :branch => 'Swift3' - pod 'Fuzi' - pod 'Try' + pod 'GRMustache.swift', '~> 2.0.0' + pod 'Fuzi', '~> 1.0.0' + pod 'Try', '~> 1.0.0' end From 739f4458f7119043d5461c301285d45e740525e2 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Mon, 24 Oct 2016 13:55:48 -0400 Subject: [PATCH 04/15] The pod Try has a swift file trap.swift that is not Swift 3, but found a forked repo that is. Attempting to use that instead. --- CDAKit.podspec | 2 +- Podfile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CDAKit.podspec b/CDAKit.podspec index c94054a..3883a17 100755 --- a/CDAKit.podspec +++ b/CDAKit.podspec @@ -33,5 +33,5 @@ Pod::Spec.new do |s| s.frameworks = 'HealthKit' s.dependency 'GRMustache.swift', '~> 2.0.0' s.dependency 'Fuzi', '~> 1.0.0' - s.dependency 'Try', '~> 1.0.0' + s.dependency 'Try', :git => 'https://github.com/nikinapi/Try.git' end diff --git a/Podfile b/Podfile index 2c3a6d5..1f05531 100644 --- a/Podfile +++ b/Podfile @@ -5,12 +5,12 @@ use_frameworks! target 'CDAKit' do pod 'GRMustache.swift', '~> 2.0.0' pod 'Fuzi', '~> 1.0.0' - pod 'Try', '~> 1.0.0' + pod 'Try', :git => 'https://github.com/nikinapi/Try.git' end target 'CDAKitTests' do pod 'GRMustache.swift', '~> 2.0.0' pod 'Fuzi', '~> 1.0.0' - pod 'Try', '~> 1.0.0' + pod 'Try', :git => 'https://github.com/nikinapi/Try.git' end From 79d78be63801018a49602e123f45b4010002fa7f Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Mon, 24 Oct 2016 15:23:10 -0400 Subject: [PATCH 05/15] Could not use Try as is, as it is not Swift 3 compatible, so brought the three source files (WBTry.m, WBTry.h, trap.swift) internally, and modified trap.swift to make it Swift 3, and fixed up the CDAKit.h / umbrella framework / bridging header to use this. --- CDAKit.podspec | 1 - CDAKit.xcodeproj/project.pbxproj | 14 +++++++++ CDAKit/CDAKit-Bridging-Header.h | 4 +-- CDAKit/CDAKit.h | 1 + .../CDAKitHealthKitBridge.swift | 1 - CDAKit/health-data-standards/lib/util/WBTry.h | 27 ++++++++++++++++ CDAKit/health-data-standards/lib/util/WBTry.m | 28 +++++++++++++++++ .../health-data-standards/lib/util/trap.swift | 31 +++++++++++++++++++ Podfile | 2 -- 9 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 CDAKit/health-data-standards/lib/util/WBTry.h create mode 100644 CDAKit/health-data-standards/lib/util/WBTry.m create mode 100644 CDAKit/health-data-standards/lib/util/trap.swift diff --git a/CDAKit.podspec b/CDAKit.podspec index 3883a17..70329d7 100755 --- a/CDAKit.podspec +++ b/CDAKit.podspec @@ -33,5 +33,4 @@ Pod::Spec.new do |s| s.frameworks = 'HealthKit' s.dependency 'GRMustache.swift', '~> 2.0.0' s.dependency 'Fuzi', '~> 1.0.0' - s.dependency 'Try', :git => 'https://github.com/nikinapi/Try.git' end diff --git a/CDAKit.xcodeproj/project.pbxproj b/CDAKit.xcodeproj/project.pbxproj index 8aa6a89..66d67f9 100644 --- a/CDAKit.xcodeproj/project.pbxproj +++ b/CDAKit.xcodeproj/project.pbxproj @@ -291,6 +291,9 @@ 389172F91C6CFD9100A31299 /* risk_category_assessment_fragment.xml in Resources */ = {isa = PBXBuildFile; fileRef = 389172CF1C6CFD9000A31299 /* risk_category_assessment_fragment.xml */; }; 389172FA1C6CFD9100A31299 /* symptom_active_fragment.xml in Resources */ = {isa = PBXBuildFile; fileRef = 389172D01C6CFD9000A31299 /* symptom_active_fragment.xml */; }; 389172FB1C6CFD9100A31299 /* tobacco_use_fragment.xml in Resources */ = {isa = PBXBuildFile; fileRef = 389172D11C6CFD9000A31299 /* tobacco_use_fragment.xml */; }; + 38B938261DBE8BC30013DCD0 /* trap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38B938231DBE8BC30013DCD0 /* trap.swift */; }; + 38B938271DBE8BC30013DCD0 /* WBTry.h in Headers */ = {isa = PBXBuildFile; fileRef = 38B938241DBE8BC30013DCD0 /* WBTry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 38B938281DBE8BC30013DCD0 /* WBTry.m in Sources */ = {isa = PBXBuildFile; fileRef = 38B938251DBE8BC30013DCD0 /* WBTry.m */; }; 38BC98131C7C9F3400E8F2F4 /* CDAKRecordModels_Common.png in Resources */ = {isa = PBXBuildFile; fileRef = 38BC98121C7C9F3400E8F2F4 /* CDAKRecordModels_Common.png */; }; 38BC98151C7C9F5600E8F2F4 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 38BC98141C7C9F5600E8F2F4 /* README.md */; }; 38BC98191C7CF19D00E8F2F4 /* CDAKitGithubLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = 38BC98181C7CF19D00E8F2F4 /* CDAKitGithubLogo.png */; }; @@ -613,6 +616,9 @@ 389172CF1C6CFD9000A31299 /* risk_category_assessment_fragment.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = risk_category_assessment_fragment.xml; sourceTree = ""; }; 389172D01C6CFD9000A31299 /* symptom_active_fragment.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = symptom_active_fragment.xml; sourceTree = ""; }; 389172D11C6CFD9000A31299 /* tobacco_use_fragment.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = tobacco_use_fragment.xml; sourceTree = ""; }; + 38B938231DBE8BC30013DCD0 /* trap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = trap.swift; sourceTree = ""; }; + 38B938241DBE8BC30013DCD0 /* WBTry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBTry.h; sourceTree = ""; }; + 38B938251DBE8BC30013DCD0 /* WBTry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBTry.m; sourceTree = ""; }; 38BC98121C7C9F3400E8F2F4 /* CDAKRecordModels_Common.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CDAKRecordModels_Common.png; sourceTree = ""; }; 38BC98141C7C9F5600E8F2F4 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 38BC98181C7CF19D00E8F2F4 /* CDAKitGithubLogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CDAKitGithubLogo.png; sourceTree = ""; }; @@ -953,6 +959,9 @@ 389170BE1C6CD7FF00A31299 /* code_system_helper.swift */, 380A41081C77AECF00E5D7B8 /* CDAKVocabularyStructs.swift */, 389170BF1C6CD7FF00A31299 /* hl7_helper.swift */, + 38B938231DBE8BC30013DCD0 /* trap.swift */, + 38B938241DBE8BC30013DCD0 /* WBTry.h */, + 38B938251DBE8BC30013DCD0 /* WBTry.m */, ); path = util; sourceTree = ""; @@ -1338,6 +1347,7 @@ buildActionMask = 2147483647; files = ( 389170351C6CC1EE00A31299 /* CDAKit.h in Headers */, + 38B938271DBE8BC30013DCD0 /* WBTry.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1679,6 +1689,7 @@ 389170C11C6CD7FF00A31299 /* hl7_helper.swift in Sources */, 389170BA1C6CD7C800A31299 /* thing_with_times.swift in Sources */, 389170B71C6CD7C800A31299 /* support.swift in Sources */, + 38B938261DBE8BC30013DCD0 /* trap.swift in Sources */, 3891706B1C6CD7A500A31299 /* pedigree.swift in Sources */, 389171181C6CD8A500A31299 /* Dictionary+Extensions.swift in Sources */, 389170B91C6CD7C800A31299 /* thing_with_codes.swift in Sources */, @@ -1766,6 +1777,7 @@ 3891711F1C6CD8A500A31299 /* String+CryptoExtensions.swift in Sources */, 389171031C6CD88A00A31299 /* ccda_insurance_provider_importer.swift in Sources */, 389170B31C6CD7C800A31299 /* record.swift in Sources */, + 38B938281DBE8BC30013DCD0 /* WBTry.m in Sources */, 389170E41C6CD86D00A31299 /* cda_allergy_importer.swift in Sources */, 389170A81C6CD7C800A31299 /* medication.swift in Sources */, 389170611C6CD74500A31299 /* CDAKitHealthKitBridge.swift in Sources */, @@ -1955,6 +1967,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(SWIFT_MODULE_NAME)-Swift.h"; SWIFT_VERSION = 3.0; }; name = Debug; @@ -1976,6 +1989,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(SWIFT_MODULE_NAME)-Swift.h"; SWIFT_VERSION = 3.0; }; name = Release; diff --git a/CDAKit/CDAKit-Bridging-Header.h b/CDAKit/CDAKit-Bridging-Header.h index 4ed9a21..fab0cc7 100644 --- a/CDAKit/CDAKit-Bridging-Header.h +++ b/CDAKit/CDAKit-Bridging-Header.h @@ -1,5 +1,5 @@ #import "SwiftTryCatch.h" - +#import "WBTry.h" /* make sure you add the obj-c bridging header setting -> project\Build Settings\(search for "bridging")\(add to "Objective-C Briding Header") @@ -8,4 +8,4 @@ You may get bridging header issues if you add a folder instead of files by reference http://stackoverflow.com/questions/31628890/calling-objective-c-from-swift-class-causing-linker-errors - */ \ No newline at end of file + */ diff --git a/CDAKit/CDAKit.h b/CDAKit/CDAKit.h index cf8a919..f530c02 100644 --- a/CDAKit/CDAKit.h +++ b/CDAKit/CDAKit.h @@ -8,6 +8,7 @@ #import //#import +#import "WBTry.h" //! Project version number for CDAKit. FOUNDATION_EXPORT double CDAKitVersionNumber; diff --git a/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift b/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift index 0601f36..28d1d68 100644 --- a/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift +++ b/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift @@ -30,7 +30,6 @@ import Foundation import HealthKit -import Try /** diff --git a/CDAKit/health-data-standards/lib/util/WBTry.h b/CDAKit/health-data-standards/lib/util/WBTry.h new file mode 100644 index 0000000..05e40d9 --- /dev/null +++ b/CDAKit/health-data-standards/lib/util/WBTry.h @@ -0,0 +1,27 @@ +// +// WBTry.h +// Try +// +// Created by Jacob Berkman on 2014-08-20. +// + +#import + +@interface WBTry : NSObject + +/** + @brief Performs a block of code wrapped in Objective-C exception handling blocks. + @discussion This method accepts a block of code which is performed inside a \@try block. + If the code throws an Objective-C exception, it is caught in a \@catch. If + a catchAndRethrowBlock is provided it is executed, and if it returns YES, the + exception will be rethrown with \@throw. Lastly, if a finallyBlock is provided + we will perform it in within a \@finally block. + @param tryBlock The block to perform within a \@try block. + @param catchAndRethrowBlock An optional block that can be executed if an exception was thrown. + If it returns YES, we rethrow the exception. + @param finallyBlock An optional block that is called in the \@finally block. + + */ ++ (void)tryBlock:(nonnull void (^)(void))tryBlock catchAndRethrowBlock:(nullable BOOL (^)(_Nonnull id))catchAndRethrowBlock finallyBlock:(nullable void (^)(void))finallyBlock; + +@end diff --git a/CDAKit/health-data-standards/lib/util/WBTry.m b/CDAKit/health-data-standards/lib/util/WBTry.m new file mode 100644 index 0000000..8238f0c --- /dev/null +++ b/CDAKit/health-data-standards/lib/util/WBTry.m @@ -0,0 +1,28 @@ +// +// WBTry.m +// Try +// +// Created by Jacob Berkman on 2014-08-20. +// + +#import "WBTry.h" + +@implementation WBTry + ++ (void)tryBlock:(nonnull void (^)(void))tryBlock catchAndRethrowBlock:(nullable BOOL (^)(_Nonnull id))catchAndRethrowBlock finallyBlock:(nullable void (^)(void))finallyBlock { + @try { + tryBlock(); + } + @catch (id exception) { + if (catchAndRethrowBlock && catchAndRethrowBlock(exception)) { + @throw; + } + } + @finally { + if (finallyBlock) { + finallyBlock(); + } + } +} + +@end diff --git a/CDAKit/health-data-standards/lib/util/trap.swift b/CDAKit/health-data-standards/lib/util/trap.swift new file mode 100644 index 0000000..e114442 --- /dev/null +++ b/CDAKit/health-data-standards/lib/util/trap.swift @@ -0,0 +1,31 @@ +// +// trap.swift +// Try +// +// Created by Jacob Berkman on 2015-10-19. +// + +import Foundation + +public let tryErrorDomain = "Try" +public let tryExceptionErrorCode = 1 +public let tryExceptionErrorKey = "exception" + +/** + Wraps a closure in a `WBTry.tryBlock` to catch Objective-C exceptions using the Swift error handling model. + + - parameter block: The block of code to run within a `WBTry.tryBlock`. + - throws: Throws an `NSError` if the wrapped code throws an exception. +*/ +public func trap(_ block: @escaping () -> Void) throws { + var exception: Any? + + WBTry.try(block, catchAndRethrow: { + exception = $0 + return false + }, finallyBlock: nil) + + if let e = exception { + throw NSError(domain: tryErrorDomain, code: tryExceptionErrorCode, userInfo: [tryExceptionErrorKey: e]) + } +} diff --git a/Podfile b/Podfile index 1f05531..963a89f 100644 --- a/Podfile +++ b/Podfile @@ -5,12 +5,10 @@ use_frameworks! target 'CDAKit' do pod 'GRMustache.swift', '~> 2.0.0' pod 'Fuzi', '~> 1.0.0' - pod 'Try', :git => 'https://github.com/nikinapi/Try.git' end target 'CDAKitTests' do pod 'GRMustache.swift', '~> 2.0.0' pod 'Fuzi', '~> 1.0.0' - pod 'Try', :git => 'https://github.com/nikinapi/Try.git' end From a4a09044caf798eb18f494d5c4c106d41c92f025 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Mon, 24 Oct 2016 15:35:47 -0400 Subject: [PATCH 06/15] Including WBTry into podspec --- CDAKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CDAKit.podspec b/CDAKit.podspec index 70329d7..be8ef49 100755 --- a/CDAKit.podspec +++ b/CDAKit.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = "8.0" s.requires_arc = true - s.source_files = 'CDAKit/**/*.swift' + s.source_files = 'CDAKit/**/*.swift', 'CDAKit/**/WBTry.{h,m}' s.resource_bundles = { 'CDAKit' => [ 'CDAKit/**/*.mustache', From 809f1dbc5e99749e55d463e66528a94a89e7e2f1 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Tue, 25 Oct 2016 10:08:07 -0400 Subject: [PATCH 07/15] For Xcode 8.0, which can compile the entire project and run all tests successfully at this moment: cleaned up some warnings, fixed up one test (EntryTest, test_from_event_hash, needing to change the hash["code"]! to have two exclamation points for double optional reduction like the rest of the XCTAssertEqual tests) --- .../health-data-standards/lib/export/view_helper.swift | 5 ++++- .../lib/import/c32/c32_patient_importer.swift | 2 +- .../lib/import/cda/cda_section_importer.swift | 2 +- CDAKit/health-data-standards/lib/models/entry.swift | 3 ++- CDAKit/health-data-standards/lib/models/provider.swift | 2 +- CDAKit/health-data-standards/lib/models/record.swift | 10 ++++++++-- .../lib/util/code_system_helper.swift | 2 +- .../swift_helpers/CDAKCommonUtility.swift | 2 +- .../swift_helpers/CDAKUtility.swift | 2 +- CDAKitTests/EntryTest.swift | 2 +- 10 files changed, 21 insertions(+), 11 deletions(-) diff --git a/CDAKit/health-data-standards/lib/export/view_helper.swift b/CDAKit/health-data-standards/lib/export/view_helper.swift index 38b0c46..097cdbb 100644 --- a/CDAKit/health-data-standards/lib/export/view_helper.swift +++ b/CDAKit/health-data-standards/lib/export/view_helper.swift @@ -90,7 +90,10 @@ class ViewHelper { let code = preferred_code.code let extra_content = options["extra_content"] as? String let display = preferred_code.displayName != nil ? "displayName=\"\(preferred_code.displayName!)\"" : "" - code_string = "<\(tag_name ?? "") code=\"\(code ?? "")\" codeSystemName=\"\(pc)\" codeSystem=\"\(code_system_oid ?? "")\" \(display) \(extra_content ?? "")>" + + code_string = "<\(tag_name ?? "") code=\"\(code )\" codeSystemName=\"\(pc)\" codeSystem=\"\(code_system_oid )\" \(display) \(extra_content ?? "")>" + //-code_string = "<\(tag_name ?? "") code=\"\(code ?? "")\" codeSystemName=\"\(pc)\" codeSystem=\"\(code_system_oid ?? "")\" \(display) \(extra_content ?? "")>" + } else { let tag_name = options["tag_name"] as? String let extra_content = options["extra_content"] as? String diff --git a/CDAKit/health-data-standards/lib/import/c32/c32_patient_importer.swift b/CDAKit/health-data-standards/lib/import/c32/c32_patient_importer.swift index 370240c..30be110 100644 --- a/CDAKit/health-data-standards/lib/import/c32/c32_patient_importer.swift +++ b/CDAKit/health-data-standards/lib/import/c32/c32_patient_importer.swift @@ -151,7 +151,7 @@ class CDAKImport_C32_PatientImporter { case "medications": if let sections = sections as? [CDAKMedication] { record.medications = sections } case "conditions": if let sections = sections as? [CDAKCondition] { record.conditions = sections } case "social_history": if let sections = sections as? [CDAKSocialHistory] { record.social_history = sections } - case "care_goals": if let sections = sections as? [CDAKEntry] { record.care_goals = sections } //these are CDAKEntry records + case "care_goals": /* if let sections = sections as? [CDAKEntry] { */ record.care_goals = sections /* } */ //these are CDAKEntry records case "medical_equipment": if let sections = sections as? [CDAKMedicalEquipment] { record.medical_equipment = sections } case "allergies": if let sections = sections as? [CDAKAllergy] { record.allergies = sections } case "immunizations": if let sections = sections as? [CDAKImmunization] { record.immunizations = sections } diff --git a/CDAKit/health-data-standards/lib/import/cda/cda_section_importer.swift b/CDAKit/health-data-standards/lib/import/cda/cda_section_importer.swift index d0099b6..22b90ee 100644 --- a/CDAKit/health-data-standards/lib/import/cda/cda_section_importer.swift +++ b/CDAKit/health-data-standards/lib/import/cda/cda_section_importer.swift @@ -270,7 +270,7 @@ class CDAKImport_CDA_SectionImporter { codes.addCodes(extract_code(code_element, code_xpath: ".")) let translations = code_element.xpath("cda:translation") for translation in translations { - extract_code(translation, code_xpath: ".") + _ = extract_code(translation, code_xpath: ".") } } return codes diff --git a/CDAKit/health-data-standards/lib/models/entry.swift b/CDAKit/health-data-standards/lib/models/entry.swift index dcb86f7..c57b926 100644 --- a/CDAKit/health-data-standards/lib/models/entry.swift +++ b/CDAKit/health-data-standards/lib/models/entry.swift @@ -470,7 +470,8 @@ open class CDAKEntry: NSObject , CDAKThingWithCodes, CDAKPropertyAddressable, CD // value / unit // these won't work for the single key-value entries if let code = event["code"], let code_set = event["code_set"] as? String { - add_code(code, code_system: code_set) + add_code(code!, code_system: code_set) + //- add_code(code, code_system: code_set) } if let value = event["value"] { diff --git a/CDAKit/health-data-standards/lib/models/provider.swift b/CDAKit/health-data-standards/lib/models/provider.swift index 642e598..cd6d381 100644 --- a/CDAKit/health-data-standards/lib/models/provider.swift +++ b/CDAKit/health-data-standards/lib/models/provider.swift @@ -173,7 +173,7 @@ open class CDAKProvider: CDAKPersonable, CDAKJSONInstantiable, Hashable, Equatab // return luhn_checksum(npi[0,14]) == npi[14] //return luhn_checksum(npi[0...13]) == npi[14...14] - let result = luhn_checksum(npi.substring(with: 0..<14)) == npi.substring(with: 14..<15) + _ = luhn_checksum(npi.substring(with: 0..<14)) == npi.substring(with: 14..<15) return luhn_checksum(npi.substring(with: 0..<14)) == npi.substring(with: 14..<15) } diff --git a/CDAKit/health-data-standards/lib/models/record.swift b/CDAKit/health-data-standards/lib/models/record.swift index dfcb49a..522ebed 100644 --- a/CDAKit/health-data-standards/lib/models/record.swift +++ b/CDAKit/health-data-standards/lib/models/record.swift @@ -8,6 +8,7 @@ import Foundation import Mustache + fileprivate func < (lhs: T?, rhs: T?) -> Bool { switch (lhs, rhs) { case let (l?, r?): @@ -858,10 +859,11 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { // MARK: Standard properties ///Debugging description + /********** override open var description : String { return "CDAKRecord => prefix: \(prefix), first: \(first), last: \(last), suffix: \(suffix), gender: \(gender), birthdate: \(birthdate), deathdate: \(deathdate), religious_affiliation: \(religious_affiliation), effective_time: \(effective_time), race: \(race), ethnicity: \(ethnicity), languages = \(languages), marital_status: \(marital_status), medical_record_number: \(medical_record_number), medical_record_assigner: \(medical_record_assigner), expired: \(expired), clinicalTrialParticipant: \(clinicalTrialParticipant), allergies: \(allergies), care_goals: \(care_goals), conditions: \(conditions), encounters: \(encounters), communications: \(communications), family_history: \(family_history), immunizations: \(immunizations), medical_equipment: \(medical_equipment), medications: \(medications), procedures: \(procedures), results: \(results), social_history: \(social_history), vital_signs: \(vital_signs), advance_directives: \(advance_directives), insurance_providers: \(insurance_providers), functional_statuses: \(functional_statuses), provider_performances: \(provider_performances), addresses: \(addresses), telecoms: \(telecoms)" } - + ********/ } @@ -992,6 +994,7 @@ extension CDAKRecord { //MARK: Convenience copying public convenience init(copyFrom record: CDAKRecord) { self.init() + self.prefix = record.prefix self.first = record.first self.last = record.last @@ -1031,7 +1034,6 @@ extension CDAKRecord { self.identifiers = record.identifiers self.custodian = record.custodian self.clinicalTrialParticipant = record.clinicalTrialParticipant - } @@ -1041,6 +1043,10 @@ extension CDAKRecord { extension CDAKRecord: CDAKJSONExportable { // MARK: - JSON Generation ///Dictionary for JSON data + + //public var jsonDict: [String: AnyObject] = [:] + + public var jsonDict: [String: AnyObject] { var dict: [String: AnyObject] = [:] diff --git a/CDAKit/health-data-standards/lib/util/code_system_helper.swift b/CDAKit/health-data-standards/lib/util/code_system_helper.swift index 1dc964d..c8b0294 100644 --- a/CDAKit/health-data-standards/lib/util/code_system_helper.swift +++ b/CDAKit/health-data-standards/lib/util/code_system_helper.swift @@ -132,7 +132,7 @@ open class CDAKCodeSystemHelper { return } let cs = CDAKGlobals.sharedInstance.CDAK_EXTENDED_CODE_SYSTEMS.inverse() - if let existing_oid = cs[code_system] { + if cs[code_system] != nil { // do a reverse look-up for this code_system // we already have someting in the set - don't re-add the value for a different key // this can happen for things like bogus entries diff --git a/CDAKit/health-data-standards/swift_helpers/CDAKCommonUtility.swift b/CDAKit/health-data-standards/swift_helpers/CDAKCommonUtility.swift index 17eb9b3..d7e619c 100644 --- a/CDAKit/health-data-standards/swift_helpers/CDAKCommonUtility.swift +++ b/CDAKit/health-data-standards/swift_helpers/CDAKCommonUtility.swift @@ -215,7 +215,7 @@ class CDAKCommonUtility { do { let rawData = try JSONSerialization.data(withJSONObject: jsonDict, options: .prettyPrinted) let jsonString = NSString(data: rawData, encoding: String.Encoding.utf8.rawValue) as? String - return NSString(data: rawData, encoding: String.Encoding.utf8.rawValue) as? String + return jsonString // NSString(data: rawData, encoding: String.Encoding.utf8.rawValue) as? String } catch let error as NSError { print(error) } diff --git a/CDAKit/health-data-standards/swift_helpers/CDAKUtility.swift b/CDAKit/health-data-standards/swift_helpers/CDAKUtility.swift index 4caef37..3be2f07 100644 --- a/CDAKit/health-data-standards/swift_helpers/CDAKUtility.swift +++ b/CDAKit/health-data-standards/swift_helpers/CDAKUtility.swift @@ -359,7 +359,7 @@ class CDAKUtility { case "performer": obj.performer = CDAKProvider(event: dictionaryAny(value)) default: debug_message("CDAKEncounter", function: "setProperty", property: property) } - } else if let obj = obj as? CDAKAllergy { + } else if /* let obj = obj as? CDAKAllergy */ obj is CDAKAllergy { switch property { // case "reaction": obj.reaction = singleCodeFieldFlat(value) // case "severity": obj.severity = singleCodeFieldFlat(value) diff --git a/CDAKitTests/EntryTest.swift b/CDAKitTests/EntryTest.swift index f855bb9..46b8878 100644 --- a/CDAKitTests/EntryTest.swift +++ b/CDAKitTests/EntryTest.swift @@ -113,7 +113,7 @@ class EntryTest: XCTestCase { // print(String(hash["code"]!!)) // print(entry.codes[String(hash["code_set"]!!)]!) // XCTAssertEqual([String(hash["code"]!)], entry.codes[String(hash["code_set"]!!)]!) - XCTAssertEqual([String(describing: hash["code"]!)], [entry.codes["RxNorm"]!.first!.code]) + XCTAssertEqual([String(describing: hash["code"]!!)], [entry.codes["RxNorm"]!.first!.code]) XCTAssertEqual(String(describing: hash["value"]!!), (entry.values.first as! CDAKPhysicalQuantityResultValue).scalar) XCTAssertEqual(String(describing: hash["unit"]!!), (entry.values.first as! CDAKPhysicalQuantityResultValue).units) XCTAssertEqual(String(describing: hash["specifics"]!!), entry.specifics) From c12b3f41b6fce7711cea95419815380dde5b54b3 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Tue, 25 Oct 2016 11:46:40 -0400 Subject: [PATCH 08/15] To get CDAKit to compile with Xcode 8.1 GM, needed to break apart record.swift into 4 pieces. It may not need to actually be in 4 pieces, as I believe the val dictionary was the culprit (its a Swift compiler bug in 8.1) but now it cleanly compiles and all tests succeed in Xcode 8.1 GM --- CDAKit.xcodeproj/project.pbxproj | 12 + .../lib/models/record.swift | 425 +++--------------- .../lib/models/record1.swift | 122 +++++ .../lib/models/record2.swift | 80 ++++ .../lib/models/record3.swift | 123 +++++ 5 files changed, 406 insertions(+), 356 deletions(-) create mode 100644 CDAKit/health-data-standards/lib/models/record1.swift create mode 100644 CDAKit/health-data-standards/lib/models/record2.swift create mode 100644 CDAKit/health-data-standards/lib/models/record3.swift diff --git a/CDAKit.xcodeproj/project.pbxproj b/CDAKit.xcodeproj/project.pbxproj index 66d67f9..c95a81f 100644 --- a/CDAKit.xcodeproj/project.pbxproj +++ b/CDAKit.xcodeproj/project.pbxproj @@ -14,6 +14,8 @@ 38359E0A1C7B774400CCC036 /* CDAKit.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 38359E071C7B774400CCC036 /* CDAKit.podspec */; }; 38359E0B1C7B774400CCC036 /* LICENSE.txt in Resources */ = {isa = PBXBuildFile; fileRef = 38359E081C7B774400CCC036 /* LICENSE.txt */; }; 38359E0C1C7B774400CCC036 /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = 38359E091C7B774400CCC036 /* Podfile */; }; + 3845045B1DBFABB500FA7A27 /* record2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3845045A1DBFABB500FA7A27 /* record2.swift */; }; + 3845045D1DBFABC700FA7A27 /* record3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3845045C1DBFABC600FA7A27 /* record3.swift */; }; 384E23111C737A8C009B9DED /* 170.314(b)(1)InPt_Discharge Summary CED Type.xml in Resources */ = {isa = PBXBuildFile; fileRef = 384E23101C737A8C009B9DED /* 170.314(b)(1)InPt_Discharge Summary CED Type.xml */; }; 384E23141C738E4E009B9DED /* CDAKJSONInstantiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384E23131C738E4E009B9DED /* CDAKJSONInstantiable.swift */; }; 384E23171C73C517009B9DED /* MetadataImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384E23161C73C517009B9DED /* MetadataImporter.swift */; }; @@ -301,6 +303,7 @@ 38BE32B81C80F5EB002AEC25 /* cda_social_history_importer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38BE32B71C80F5EB002AEC25 /* cda_social_history_importer.swift */; }; 38BE32BA1C80F7A9002AEC25 /* ccda_medication_importer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38BE32B91C80F7A9002AEC25 /* ccda_medication_importer.swift */; }; 38BE32BC1C81002F002AEC25 /* c32_provider_performer.c32.mustache in Resources */ = {isa = PBXBuildFile; fileRef = 38BE32BB1C81002F002AEC25 /* c32_provider_performer.c32.mustache */; }; + 38C30C061DBFA6D5009652B8 /* record1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38C30C051DBFA6D5009652B8 /* record1.swift */; }; 38CB596B1C8720D4004630F9 /* ccda_code_without_reference.ccda.mustache in Resources */ = {isa = PBXBuildFile; fileRef = 38CB596A1C8720D4004630F9 /* ccda_code_without_reference.ccda.mustache */; }; 38CB596D1C8731BD004630F9 /* ccda_medication_dose.ccda.mustache in Resources */ = {isa = PBXBuildFile; fileRef = 38CB596C1C8731BD004630F9 /* ccda_medication_dose.ccda.mustache */; }; 38CB596F1C8736B0004630F9 /* ccda_medication_admin_timing.ccda.mustache in Resources */ = {isa = PBXBuildFile; fileRef = 38CB596E1C8736B0004630F9 /* ccda_medication_admin_timing.ccda.mustache */; }; @@ -335,6 +338,8 @@ 38359E071C7B774400CCC036 /* CDAKit.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CDAKit.podspec; sourceTree = ""; }; 38359E081C7B774400CCC036 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; 38359E091C7B774400CCC036 /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 3845045A1DBFABB500FA7A27 /* record2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = record2.swift; sourceTree = ""; }; + 3845045C1DBFABC600FA7A27 /* record3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = record3.swift; sourceTree = ""; }; 384E23101C737A8C009B9DED /* 170.314(b)(1)InPt_Discharge Summary CED Type.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "170.314(b)(1)InPt_Discharge Summary CED Type.xml"; sourceTree = ""; }; 384E23131C738E4E009B9DED /* CDAKJSONInstantiable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CDAKJSONInstantiable.swift; sourceTree = ""; }; 384E23161C73C517009B9DED /* MetadataImporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetadataImporter.swift; sourceTree = ""; }; @@ -626,6 +631,7 @@ 38BE32B71C80F5EB002AEC25 /* cda_social_history_importer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = cda_social_history_importer.swift; sourceTree = ""; }; 38BE32B91C80F7A9002AEC25 /* ccda_medication_importer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ccda_medication_importer.swift; sourceTree = ""; }; 38BE32BB1C81002F002AEC25 /* c32_provider_performer.c32.mustache */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = c32_provider_performer.c32.mustache; sourceTree = ""; }; + 38C30C051DBFA6D5009652B8 /* record1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = record1.swift; sourceTree = ""; }; 38CB596A1C8720D4004630F9 /* ccda_code_without_reference.ccda.mustache */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ccda_code_without_reference.ccda.mustache; sourceTree = ""; }; 38CB596C1C8731BD004630F9 /* ccda_medication_dose.ccda.mustache */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ccda_medication_dose.ccda.mustache; sourceTree = ""; }; 38CB596E1C8736B0004630F9 /* ccda_medication_admin_timing.ccda.mustache */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ccda_medication_admin_timing.ccda.mustache; sourceTree = ""; }; @@ -1002,6 +1008,9 @@ 389170881C6CD7C800A31299 /* provider.swift */, 389170891C6CD7C800A31299 /* reason.swift */, 3891708A1C6CD7C800A31299 /* record.swift */, + 38C30C051DBFA6D5009652B8 /* record1.swift */, + 3845045A1DBFABB500FA7A27 /* record2.swift */, + 3845045C1DBFABC600FA7A27 /* record3.swift */, 3891708B1C6CD7C800A31299 /* reference.swift */, 3891708C1C6CD7C800A31299 /* result_value.swift */, 3891708D1C6CD7C800A31299 /* social_history.swift */, @@ -1743,12 +1752,15 @@ 389170AB1C6CD7C800A31299 /* person.swift in Sources */, 389171091C6CD88A00A31299 /* ccda_vital_sign_importer.swift in Sources */, 389170EE1C6CD86D00A31299 /* cda_provider_importer.swift in Sources */, + 38C30C061DBFA6D5009652B8 /* record1.swift in Sources */, 384E23221C73C7A2009B9DED /* CDAKQRDAHeader.swift in Sources */, + 3845045B1DBFABB500FA7A27 /* record2.swift in Sources */, 389171021C6CD88A00A31299 /* ccda_immunization_importer.swift in Sources */, 384E23201C73C797009B9DED /* CDAKQRDADevice.swift in Sources */, 389170A51C6CD7C800A31299 /* insurance_provider.swift in Sources */, 3891711B1C6CD8A500A31299 /* CDAKValueAndUnit.swift in Sources */, 389170C51C6CD81900A31299 /* HDSExport.swift in Sources */, + 3845045D1DBFABC700FA7A27 /* record3.swift in Sources */, 384E23241C73C7CE009B9DED /* CDAKQRDALegalAuthenticator.swift in Sources */, 389170A11C6CD7C800A31299 /* fulfillment_history.swift in Sources */, 389170C61C6CD81900A31299 /* template_helper.swift in Sources */, diff --git a/CDAKit/health-data-standards/lib/models/record.swift b/CDAKit/health-data-standards/lib/models/record.swift index 522ebed..2bb28aa 100644 --- a/CDAKit/health-data-standards/lib/models/record.swift +++ b/CDAKit/health-data-standards/lib/models/record.swift @@ -448,71 +448,71 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { "medications", "procedures", "results", "communications", "family_history", "social_history", "vital_signs", "support", "advance_directives", "insurance_providers", "functional_statuses"] - ///Legacy Ruby. Search for record(s) by provider. - internal class func by_provider(_ provider: CDAKProvider, effective_date: Double?) -> [CDAKRecord] { - // FIX_ME: this is a mess - var records = [CDAKRecord]() - if let effective_date = effective_date { - var a_provider: CDAKProvider? - a_provider = provider_queries(provider.npi!, effective_date: effective_date) - for record in CDAKGlobals.sharedInstance.CDAKRecords { - for perf in record.provider_performances { - if perf.provider?.npi == a_provider?.npi { - records.append(record) - } - } - } - } else { - //: where('provider_performances.provider_id'=>prov.id) - for record in CDAKGlobals.sharedInstance.CDAKRecords { - for perf in record.provider_performances { - if perf.provider?.npi == provider.npi { - records.append(record) - } - } - } - } - - return records - } - - //scope :by_patient_id, ->(id) { where(:medical_record_number => id) } - ///Legacy Ruby. Searches for a patient record by patient MRN - internal class func by_patient_id(_ id: String) -> [CDAKRecord] { - //FIX_ME: Should this return just one record? - var records = [CDAKRecord]() - for record in CDAKGlobals.sharedInstance.CDAKRecords { - if record.medical_record_number == id { - records.append(record) - } - } - return records - } - - ///Legacy Ruby. Determines if a record exists already in the record collection - internal class func update_or_create(_ data: CDAKRecord) -> CDAKRecord { - //existing = CDAKRecord.where(medical_record_number: data.medical_record_number).first - var existing: CDAKRecord? - for record in CDAKGlobals.sharedInstance.CDAKRecords { - if record.medical_record_number == data.medical_record_number { - existing = record - } - } - if var existing = existing { - //FIX_ME: this is just horribly dangerous - //kludgy (and probably wrong) work-around for Ruby's being able to just magically copy - //existing.update_attributes!(data.attributes.except('_id')) - existing = data.copy() as! CDAKRecord - return existing - } else { - return data - } - } - - ///Legacy Ruby. Returns all providers contained in provider performances - internal func providers() -> [CDAKProvider] { - return provider_performances.filter({pp in pp.provider != nil}).map({pp in pp.provider!}) - } +// ///Legacy Ruby. Search for record(s) by provider. +// internal class func by_provider(_ provider: CDAKProvider, effective_date: Double?) -> [CDAKRecord] { +// // FIX_ME: this is a mess +// var records = [CDAKRecord]() +// if let effective_date = effective_date { +// var a_provider: CDAKProvider? +// a_provider = provider_queries(provider.npi!, effective_date: effective_date) +// for record in CDAKGlobals.sharedInstance.CDAKRecords { +// for perf in record.provider_performances { +// if perf.provider?.npi == a_provider?.npi { +// records.append(record) +// } +// } +// } +// } else { +// //: where('provider_performances.provider_id'=>prov.id) +// for record in CDAKGlobals.sharedInstance.CDAKRecords { +// for perf in record.provider_performances { +// if perf.provider?.npi == provider.npi { +// records.append(record) +// } +// } +// } +// } +// +// return records +// } +// +// //scope :by_patient_id, ->(id) { where(:medical_record_number => id) } +// ///Legacy Ruby. Searches for a patient record by patient MRN +// internal class func by_patient_id(_ id: String) -> [CDAKRecord] { +// //FIX_ME: Should this return just one record? +// var records = [CDAKRecord]() +// for record in CDAKGlobals.sharedInstance.CDAKRecords { +// if record.medical_record_number == id { +// records.append(record) +// } +// } +// return records +// } +// +// ///Legacy Ruby. Determines if a record exists already in the record collection +// internal class func update_or_create(_ data: CDAKRecord) -> CDAKRecord { +// //existing = CDAKRecord.where(medical_record_number: data.medical_record_number).first +// var existing: CDAKRecord? +// for record in CDAKGlobals.sharedInstance.CDAKRecords { +// if record.medical_record_number == data.medical_record_number { +// existing = record +// } +// } +// if var existing = existing { +// //FIX_ME: this is just horribly dangerous +// //kludgy (and probably wrong) work-around for Ruby's being able to just magically copy +// //existing.update_attributes!(data.attributes.except('_id')) +// existing = data.copy() as! CDAKRecord +// return existing +// } else { +// return data +// } +// } +// +// ///Legacy Ruby. Returns all providers contained in provider performances +// internal func providers() -> [CDAKProvider] { +// return provider_performances.filter({pp in pp.provider != nil}).map({pp in pp.provider!}) +// } ///returns a specific set of patient entry records based on the supplied section name (if found) @@ -582,7 +582,7 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { //removed the original "flatten" since we're just merging the contents of the array and not arrays in arrays return matching_entries_by_section } - + ///Combines all entries into a single collection and returns them internal var entries: [CDAKEntry] { var all_entries = [CDAKEntry]() @@ -592,7 +592,7 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } return all_entries } - + /** Remove duplicate entries from a section based on cda_identifier or id. @@ -713,7 +713,7 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - + /* fileprivate class func provider_queries(_ provider_id: String, effective_date: Double) -> CDAKProvider? { //FIX_ME: - review implementation for accuracy //Making the (probably bad) assumption these return a single value - provider_id assumed to be unique @@ -746,7 +746,7 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } return nil } - + */ // MARK: - Initializers required override public init() { // <== Need "required" because we need to call dynamicType() below @@ -866,290 +866,3 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { ********/ } - -extension CDAKRecord { - // MARK: - Mustache marshalling - override open var mustacheBox: MustacheBox { - var vals: [String:MustacheBox] = [String:MustacheBox]() - var defaultLanguage: CDAKCodedEntries = CDAKCodedEntries() - defaultLanguage.addCodes("IETF", code: "en-US") - let defaultLanguages: [CDAKCodedEntries] = [defaultLanguage] - vals = [ - "id": Box(self._id), - "prefix": Box(self.prefix), - "first": Box(self.first), - "last": Box(self.last), - "suffix": Box(self.suffix), - "gender": Box(self.gender), - "birthdate": Box(self.birthdate), - "deathdate": Box(self.deathdate), - "religious_affiliation": Box(self.religious_affiliation), - "effective_time": Box(self.effective_time), - "race": Box(self.race), - "ethnicity": Box(self.ethnicity), - "languages": self.languages.count > 0 ? Box(self.languages) : Box(defaultLanguages), - "marital_status": Box(self.marital_status), - "medical_record_number": Box(self.medical_record_number), - "medical_record_assigner": Box(self.medical_record_assigner), - "expired": Box(self.expired), - "addresses": Box(self.addresses), - "telecoms": Box(self.telecoms) - ] - - if identifiers.count > 0 { - vals["identifiers"] = Box(self.identifiers) - } - - - // we can't pass locals into mustache like we can with erb, so we're cheating - // when we marshall the data, we're setting up template block values here instead - // you can use template values from here - /* - key, section, entries, status, value - */ - if let entries = boxEntries(allergies, section: "allergies") { - vals["allergies"] = entries - } - if let entries = boxEntries(results, section: "results", value: true) { - vals["results"] = entries - } - if let entries = boxEntries(medications, section: "medications") { - vals["medications"] = entries - } - if let entries = boxEntries(care_goals, section: "plan_of_care") { - vals["care_goals"] = entries - } - if let entries = boxEntries(conditions, section: "conditions", status: true) { - vals["conditions"] = entries - } - if let entries = boxEntries(social_history, section: "social_history") { - vals["social_history"] = entries - } - if let entries = boxEntries(immunizations, section: "immunizations") { - vals["immunizations"] = entries - } - if let entries = boxEntries(medical_equipment, section: "medical_equipment") { - vals["medical_equipment"] = entries - } - if let entries = boxEntries(encounters, section: "encounters") { - vals["encounters"] = entries - } - if let entries = boxEntries(procedures, section: "procedures") { - vals["procedures"] = entries - } - if let entries = boxEntries(vital_signs, section: "vitals", value: true) { - vals["vital_signs"] = entries - } - - if let header = header { - vals["header"] = Box(header) - } - - if provider_performances.count > 0 { - vals["provider_performances"] = Box(provider_performances) - } - - - return Box(vals) - } - - func boxEntries(_ entries: [CDAKEntry], section: String, status: Bool = false, value: Bool = false) -> MustacheBox? { - if entries.count > 0 { - return Box([ - "section" : Box(section), - "status" : Box(status), - "value" : Box(value), - "entries": Box(entries) - ]) - } - return nil - } - -} - - - -extension CDAKRecord { - //MARK: Primary CDA import / export Methods - /** - Master public convenience method for exporting record to CDA - - Formats defined in: CDAKExport.CDAKExportFormat - - EX: .ccda or .c32 - - */ - public func export(inFormat format: CDAKExport.CDAKExportFormat) -> String { - return CDAKExport.export(patientRecord: self, inFormat: format) - } - - /** - Creates a new record from CDA XML - */ - public convenience init(fromXML doc: String) throws { - let x = try CDAKImport_BulkRecordImporter.importRecord(doc) - self.init(copyFrom: x) - } - - //MARK: Convenience copying - public convenience init(copyFrom record: CDAKRecord) { - self.init() - - self.prefix = record.prefix - self.first = record.first - self.last = record.last - self.suffix = record.suffix - self.gender = record.gender - self.birthdate = record.birthdate - self.deathdate = record.deathdate - self.religious_affiliation = record.religious_affiliation - self.effective_time = record.effective_time - self.race = record.race - self.ethnicity = record.ethnicity - self.languages = record.languages - self.marital_status = record.marital_status - self.medical_record_number = record.medical_record_number - self.medical_record_assigner = record.medical_record_assigner - self.expired = record.expired - self.allergies = record.allergies - self.care_goals = record.care_goals - self.conditions = record.conditions - self.encounters = record.encounters - self.communications = record.communications - self.family_history = record.family_history - self.immunizations = record.immunizations - self.medical_equipment = record.medical_equipment - self.medications = record.medications - self.procedures = record.procedures - self.results = record.results - self.socialhistories = record.socialhistories - self.vital_signs = record.vital_signs - self.support = record.support - self.advance_directives = record.advance_directives - self.insurance_providers = record.insurance_providers - self.functional_statuses = record.functional_statuses - self.provider_performances = record.provider_performances - self.addresses = record.addresses - self.telecoms = record.telecoms - self.identifiers = record.identifiers - self.custodian = record.custodian - self.clinicalTrialParticipant = record.clinicalTrialParticipant - } - - -} - - -extension CDAKRecord: CDAKJSONExportable { - // MARK: - JSON Generation - ///Dictionary for JSON data - - //public var jsonDict: [String: AnyObject] = [:] - - - public var jsonDict: [String: AnyObject] { - var dict: [String: AnyObject] = [:] - - if identifiers.count > 0 { - dict["identifiers"] = identifiers.map({$0.jsonDict}) as AnyObject? - } - - if let prefix = prefix { - dict["prefix"] = prefix as AnyObject? - } - if let first = first { - dict["first"] = first as AnyObject? - } - if let last = last { - dict["last"] = last as AnyObject? - } - if let suffix = suffix { - dict["suffix"] = suffix as AnyObject? - } - if let gender = gender { - dict["gender"] = gender as AnyObject? - } - if let birthdate = birthdate { - dict["birthdate"] = birthdate as AnyObject? - } - if let deathdate = deathdate { - dict["deathdate"] = deathdate as AnyObject? - } - - if religious_affiliation.count > 0 { - dict["religious_affiliation"] = religious_affiliation.codes.map({$0.jsonDict}) as AnyObject? - } - - if let effective_time = effective_time { - dict["effective_time"] = effective_time as AnyObject? - } - - dict["id"] = _id as AnyObject? - - if let header = header { - dict["header"] = header.jsonDict as AnyObject? - } - - if pregnancies.count > 0 { - dict["pregnancies"] = pregnancies.map({$0.jsonDict}) as AnyObject? - } - if race.count > 0 { - dict["race"] = race.codes.map({$0.jsonDict}) as AnyObject? - } - if ethnicity.count > 0 { - dict["ethnicity"] = ethnicity.codes.map({$0.jsonDict}) as AnyObject? - } - - if languages.count > 0 { - dict["languages"] = languages.map({$0.jsonDict}) as AnyObject? - } - - if marital_status.count > 0 { - dict["marital_status"] = marital_status.codes.map({$0.jsonDict}) as AnyObject? - } - - if let medical_record_number = medical_record_number { - dict["medical_record_number"] = medical_record_number as AnyObject? - } - - if let medical_record_assigner = medical_record_assigner { - dict["medical_record_assigner"] = medical_record_assigner as AnyObject? - } - - if let expired = expired { - dict["expired"] = expired as AnyObject? - } - - if let clinicalTrialParticipant = clinicalTrialParticipant { - dict["clinicalTrialParticipant"] = clinicalTrialParticipant as AnyObject? - } - - if let custodian = custodian { - dict["custodian"] = custodian as AnyObject? - } - - if allergies.count > 0 { dict["allergies"] = allergies.map({$0.jsonDict}) as AnyObject? } - if care_goals.count > 0 { dict["care_goals"] = care_goals.map({$0.jsonDict}) as AnyObject?} - if conditions.count > 0 { dict["conditions"] = conditions.map({$0.jsonDict}) as AnyObject? } - if encounters.count > 0 { dict["encounters"] = encounters.map({$0.jsonDict}) as AnyObject? } - if communications.count > 0 { dict["communications"] = communications.map({$0.jsonDict}) as AnyObject? } - if family_history.count > 0 { dict["family_history"] = family_history.map({$0.jsonDict}) as AnyObject? } - if immunizations.count > 0 { dict["immunizations"] = immunizations.map({$0.jsonDict}) as AnyObject? } - if medical_equipment.count > 0 { dict["medical_equipment"] = medical_equipment.map({$0.jsonDict}) as AnyObject?} - if medications.count > 0 { dict["medications"] = medications.map({$0.jsonDict}) as AnyObject? } - if procedures.count > 0 { dict["procedures"] = procedures.map({$0.jsonDict}) as AnyObject? } - if results.count > 0 { dict["results"] = results.map({$0.jsonDict}) as AnyObject? } - if social_history.count > 0 { dict["social_history"] = social_history.map({$0.jsonDict}) as AnyObject? } - if vital_signs.count > 0 { dict["vital_signs"] = vital_signs.map({$0.jsonDict}) as AnyObject? } - if support.count > 0 { dict["support"] = support.map({$0.jsonDict}) as AnyObject? } - if advance_directives.count > 0 { dict["advance_directives"] = advance_directives.map({$0.jsonDict}) as AnyObject? } - if insurance_providers.count > 0 { dict["insurance_providers"] = insurance_providers.map({$0.jsonDict}) as AnyObject?} - if functional_statuses.count > 0 { dict["functional_statuses"] = functional_statuses.map({$0.jsonDict}) as AnyObject?} - if provider_performances.count > 0 { dict["provider_performances"] = provider_performances.map({$0.jsonDict}) as AnyObject?} - if addresses.count > 0 { dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } - if telecoms.count > 0 { dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject?} - - - return dict - } -} diff --git a/CDAKit/health-data-standards/lib/models/record1.swift b/CDAKit/health-data-standards/lib/models/record1.swift new file mode 100644 index 0000000..7d1c4a9 --- /dev/null +++ b/CDAKit/health-data-standards/lib/models/record1.swift @@ -0,0 +1,122 @@ +// +// record1.swift +// CDAKit +// +// Created by Jim on 10/25/16. +// Copyright © 2016 Eric Whitley. All rights reserved. +// + +import Foundation +import Mustache + + +extension CDAKRecord { + + // MARK: - Mustache marshalling + override open var mustacheBox: MustacheBox { + + //var vals: [String:MustacheBox] = [:] // [String:MustacheBox]() + var defaultLanguage: CDAKCodedEntries = CDAKCodedEntries() + defaultLanguage.addCodes("IETF", code: "en-US") + let defaultLanguages: [CDAKCodedEntries] = [defaultLanguage] + + var vals: [String:MustacheBox] = [ + "id": Box(self._id), + "prefix": Box(self.prefix), + "first": Box(self.first), + "last": Box(self.last), + "suffix": Box(self.suffix), + "gender": Box(self.gender), + "birthdate": Box(self.birthdate), + "deathdate": Box(self.deathdate), + "religious_affiliation": Box(self.religious_affiliation), + "effective_time": Box(self.effective_time), + "race": Box(self.race), + "ethnicity": Box(self.ethnicity), + "languages": self.languages.count > 0 ? Box(self.languages) : Box(defaultLanguages), + "marital_status": Box(self.marital_status), + "medical_record_number": Box(self.medical_record_number), + "medical_record_assigner": Box(self.medical_record_assigner), + "expired": Box(self.expired), + "addresses": Box(self.addresses), + "telecoms": Box(self.telecoms) + ] + + if identifiers.count > 0 { + vals["identifiers"] = Box(self.identifiers) + } + + + // we can't pass locals into mustache like we can with erb, so we're cheating + // when we marshall the data, we're setting up template block values here instead + // you can use template values from here + /* + key, section, entries, status, value + */ + if let entries = boxEntries(allergies, section: "allergies") { + vals["allergies"] = entries + } + if let entries = boxEntries(results, section: "results", value: true) { + vals["results"] = entries + } + if let entries = boxEntries(medications, section: "medications") { + vals["medications"] = entries + } + if let entries = boxEntries(care_goals, section: "plan_of_care") { + vals["care_goals"] = entries + } + if let entries = boxEntries(conditions, section: "conditions", status: true) { + vals["conditions"] = entries + } + if let entries = boxEntries(social_history, section: "social_history") { + vals["social_history"] = entries + } + if let entries = boxEntries(immunizations, section: "immunizations") { + vals["immunizations"] = entries + } + if let entries = boxEntries(medical_equipment, section: "medical_equipment") { + vals["medical_equipment"] = entries + } + if let entries = boxEntries(encounters, section: "encounters") { + vals["encounters"] = entries + } + if let entries = boxEntries(procedures, section: "procedures") { + vals["procedures"] = entries + } + if let entries = boxEntries(vital_signs, section: "vitals", value: true) { + vals["vital_signs"] = entries + } + + if let header = header { + vals["header"] = Box(header) + } + + if provider_performances.count > 0 { + vals["provider_performances"] = Box(provider_performances) + } + + + return Box(vals) + } + + func boxEntries(_ entries: [CDAKEntry], section: String, status: Bool = false, value: Bool = false) -> MustacheBox? { + + if entries.count > 0 { + + let toBox = [ + "section" : Box(section), + "status" : Box(status), + "value" : Box(value), + "entries": Box(entries) + ] + + return Box(toBox) + } + + return nil + } + +} + + + diff --git a/CDAKit/health-data-standards/lib/models/record2.swift b/CDAKit/health-data-standards/lib/models/record2.swift new file mode 100644 index 0000000..a827788 --- /dev/null +++ b/CDAKit/health-data-standards/lib/models/record2.swift @@ -0,0 +1,80 @@ +// +// record2.swift +// CDAKit +// +// Created by Jim on 10/25/16. +// Copyright © 2016 Eric Whitley. All rights reserved. +// + +import Foundation + + +extension CDAKRecord { + //MARK: Primary CDA import / export Methods + /** + Master public convenience method for exporting record to CDA + + Formats defined in: CDAKExport.CDAKExportFormat + + EX: .ccda or .c32 + + */ + public func export(inFormat format: CDAKExport.CDAKExportFormat) -> String { + return CDAKExport.export(patientRecord: self, inFormat: format) + } + + /** + Creates a new record from CDA XML + */ + public convenience init(fromXML doc: String) throws { + let x = try CDAKImport_BulkRecordImporter.importRecord(doc) + self.init(copyFrom: x) + } + + //MARK: Convenience copying + public convenience init(copyFrom record: CDAKRecord) { + self.init() + + self.prefix = record.prefix + self.first = record.first + self.last = record.last + self.suffix = record.suffix + self.gender = record.gender + self.birthdate = record.birthdate + self.deathdate = record.deathdate + self.religious_affiliation = record.religious_affiliation + self.effective_time = record.effective_time + self.race = record.race + self.ethnicity = record.ethnicity + self.languages = record.languages + self.marital_status = record.marital_status + self.medical_record_number = record.medical_record_number + self.medical_record_assigner = record.medical_record_assigner + self.expired = record.expired + self.allergies = record.allergies + self.care_goals = record.care_goals + self.conditions = record.conditions + self.encounters = record.encounters + self.communications = record.communications + self.family_history = record.family_history + self.immunizations = record.immunizations + self.medical_equipment = record.medical_equipment + self.medications = record.medications + self.procedures = record.procedures + self.results = record.results + self.socialhistories = record.socialhistories + self.vital_signs = record.vital_signs + self.support = record.support + self.advance_directives = record.advance_directives + self.insurance_providers = record.insurance_providers + self.functional_statuses = record.functional_statuses + self.provider_performances = record.provider_performances + self.addresses = record.addresses + self.telecoms = record.telecoms + self.identifiers = record.identifiers + self.custodian = record.custodian + self.clinicalTrialParticipant = record.clinicalTrialParticipant + } + + +} diff --git a/CDAKit/health-data-standards/lib/models/record3.swift b/CDAKit/health-data-standards/lib/models/record3.swift new file mode 100644 index 0000000..6156ba1 --- /dev/null +++ b/CDAKit/health-data-standards/lib/models/record3.swift @@ -0,0 +1,123 @@ +// +// record3.swift +// CDAKit +// +// Created by Jim on 10/25/16. +// Copyright © 2016 Eric Whitley. All rights reserved. +// + +import Foundation + +extension CDAKRecord: CDAKJSONExportable { + // MARK: - JSON Generation + ///Dictionary for JSON data + + //public var jsonDict: [String: AnyObject] = [:] + + + public var jsonDict: [String: AnyObject] { + var dict: [String: AnyObject] = [:] + + if identifiers.count > 0 { + dict["identifiers"] = identifiers.map({$0.jsonDict}) as AnyObject? + } + + if let prefix = prefix { + dict["prefix"] = prefix as AnyObject? + } + if let first = first { + dict["first"] = first as AnyObject? + } + if let last = last { + dict["last"] = last as AnyObject? + } + if let suffix = suffix { + dict["suffix"] = suffix as AnyObject? + } + if let gender = gender { + dict["gender"] = gender as AnyObject? + } + if let birthdate = birthdate { + dict["birthdate"] = birthdate as AnyObject? + } + if let deathdate = deathdate { + dict["deathdate"] = deathdate as AnyObject? + } + + if religious_affiliation.count > 0 { + dict["religious_affiliation"] = religious_affiliation.codes.map({$0.jsonDict}) as AnyObject? + } + + if let effective_time = effective_time { + dict["effective_time"] = effective_time as AnyObject? + } + + dict["id"] = _id as AnyObject? + + if let header = header { + dict["header"] = header.jsonDict as AnyObject? + } + + if pregnancies.count > 0 { + dict["pregnancies"] = pregnancies.map({$0.jsonDict}) as AnyObject? + } + if race.count > 0 { + dict["race"] = race.codes.map({$0.jsonDict}) as AnyObject? + } + if ethnicity.count > 0 { + dict["ethnicity"] = ethnicity.codes.map({$0.jsonDict}) as AnyObject? + } + + if languages.count > 0 { + dict["languages"] = languages.map({$0.jsonDict}) as AnyObject? + } + + if marital_status.count > 0 { + dict["marital_status"] = marital_status.codes.map({$0.jsonDict}) as AnyObject? + } + + if let medical_record_number = medical_record_number { + dict["medical_record_number"] = medical_record_number as AnyObject? + } + + if let medical_record_assigner = medical_record_assigner { + dict["medical_record_assigner"] = medical_record_assigner as AnyObject? + } + + if let expired = expired { + dict["expired"] = expired as AnyObject? + } + + if let clinicalTrialParticipant = clinicalTrialParticipant { + dict["clinicalTrialParticipant"] = clinicalTrialParticipant as AnyObject? + } + + if let custodian = custodian { + dict["custodian"] = custodian as AnyObject? + } + + if allergies.count > 0 { dict["allergies"] = allergies.map({$0.jsonDict}) as AnyObject? } + if care_goals.count > 0 { dict["care_goals"] = care_goals.map({$0.jsonDict}) as AnyObject?} + if conditions.count > 0 { dict["conditions"] = conditions.map({$0.jsonDict}) as AnyObject? } + if encounters.count > 0 { dict["encounters"] = encounters.map({$0.jsonDict}) as AnyObject? } + if communications.count > 0 { dict["communications"] = communications.map({$0.jsonDict}) as AnyObject? } + if family_history.count > 0 { dict["family_history"] = family_history.map({$0.jsonDict}) as AnyObject? } + if immunizations.count > 0 { dict["immunizations"] = immunizations.map({$0.jsonDict}) as AnyObject? } + if medical_equipment.count > 0 { dict["medical_equipment"] = medical_equipment.map({$0.jsonDict}) as AnyObject?} + if medications.count > 0 { dict["medications"] = medications.map({$0.jsonDict}) as AnyObject? } + if procedures.count > 0 { dict["procedures"] = procedures.map({$0.jsonDict}) as AnyObject? } + if results.count > 0 { dict["results"] = results.map({$0.jsonDict}) as AnyObject? } + if social_history.count > 0 { dict["social_history"] = social_history.map({$0.jsonDict}) as AnyObject? } + if vital_signs.count > 0 { dict["vital_signs"] = vital_signs.map({$0.jsonDict}) as AnyObject? } + if support.count > 0 { dict["support"] = support.map({$0.jsonDict}) as AnyObject? } + if advance_directives.count > 0 { dict["advance_directives"] = advance_directives.map({$0.jsonDict}) as AnyObject? } + if insurance_providers.count > 0 { dict["insurance_providers"] = insurance_providers.map({$0.jsonDict}) as AnyObject?} + if functional_statuses.count > 0 { dict["functional_statuses"] = functional_statuses.map({$0.jsonDict}) as AnyObject?} + if provider_performances.count > 0 { dict["provider_performances"] = provider_performances.map({$0.jsonDict}) as AnyObject?} + if addresses.count > 0 { dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } + if telecoms.count > 0 { dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject?} + + + return dict + } +} From c832bfba742230c9e4615b8b3994557ec06ede97 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Tue, 25 Oct 2016 11:54:22 -0400 Subject: [PATCH 09/15] Uncommented funcs and statements to determine earlier compile hangs. Now everything should be back to where it originally was after the main port to Swift 3. --- .../lib/models/record.swift | 138 +++++++++--------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/CDAKit/health-data-standards/lib/models/record.swift b/CDAKit/health-data-standards/lib/models/record.swift index 2bb28aa..67bec43 100644 --- a/CDAKit/health-data-standards/lib/models/record.swift +++ b/CDAKit/health-data-standards/lib/models/record.swift @@ -448,71 +448,71 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { "medications", "procedures", "results", "communications", "family_history", "social_history", "vital_signs", "support", "advance_directives", "insurance_providers", "functional_statuses"] -// ///Legacy Ruby. Search for record(s) by provider. -// internal class func by_provider(_ provider: CDAKProvider, effective_date: Double?) -> [CDAKRecord] { -// // FIX_ME: this is a mess -// var records = [CDAKRecord]() -// if let effective_date = effective_date { -// var a_provider: CDAKProvider? -// a_provider = provider_queries(provider.npi!, effective_date: effective_date) -// for record in CDAKGlobals.sharedInstance.CDAKRecords { -// for perf in record.provider_performances { -// if perf.provider?.npi == a_provider?.npi { -// records.append(record) -// } -// } -// } -// } else { -// //: where('provider_performances.provider_id'=>prov.id) -// for record in CDAKGlobals.sharedInstance.CDAKRecords { -// for perf in record.provider_performances { -// if perf.provider?.npi == provider.npi { -// records.append(record) -// } -// } -// } -// } -// -// return records -// } -// -// //scope :by_patient_id, ->(id) { where(:medical_record_number => id) } -// ///Legacy Ruby. Searches for a patient record by patient MRN -// internal class func by_patient_id(_ id: String) -> [CDAKRecord] { -// //FIX_ME: Should this return just one record? -// var records = [CDAKRecord]() -// for record in CDAKGlobals.sharedInstance.CDAKRecords { -// if record.medical_record_number == id { -// records.append(record) -// } -// } -// return records -// } -// -// ///Legacy Ruby. Determines if a record exists already in the record collection -// internal class func update_or_create(_ data: CDAKRecord) -> CDAKRecord { -// //existing = CDAKRecord.where(medical_record_number: data.medical_record_number).first -// var existing: CDAKRecord? -// for record in CDAKGlobals.sharedInstance.CDAKRecords { -// if record.medical_record_number == data.medical_record_number { -// existing = record -// } -// } -// if var existing = existing { -// //FIX_ME: this is just horribly dangerous -// //kludgy (and probably wrong) work-around for Ruby's being able to just magically copy -// //existing.update_attributes!(data.attributes.except('_id')) -// existing = data.copy() as! CDAKRecord -// return existing -// } else { -// return data -// } -// } -// -// ///Legacy Ruby. Returns all providers contained in provider performances -// internal func providers() -> [CDAKProvider] { -// return provider_performances.filter({pp in pp.provider != nil}).map({pp in pp.provider!}) -// } + ///Legacy Ruby. Search for record(s) by provider. + internal class func by_provider(_ provider: CDAKProvider, effective_date: Double?) -> [CDAKRecord] { + // FIX_ME: this is a mess + var records = [CDAKRecord]() + if let effective_date = effective_date { + var a_provider: CDAKProvider? + a_provider = provider_queries(provider.npi!, effective_date: effective_date) + for record in CDAKGlobals.sharedInstance.CDAKRecords { + for perf in record.provider_performances { + if perf.provider?.npi == a_provider?.npi { + records.append(record) + } + } + } + } else { + //: where('provider_performances.provider_id'=>prov.id) + for record in CDAKGlobals.sharedInstance.CDAKRecords { + for perf in record.provider_performances { + if perf.provider?.npi == provider.npi { + records.append(record) + } + } + } + } + + return records + } + + //scope :by_patient_id, ->(id) { where(:medical_record_number => id) } + ///Legacy Ruby. Searches for a patient record by patient MRN + internal class func by_patient_id(_ id: String) -> [CDAKRecord] { + //FIX_ME: Should this return just one record? + var records = [CDAKRecord]() + for record in CDAKGlobals.sharedInstance.CDAKRecords { + if record.medical_record_number == id { + records.append(record) + } + } + return records + } + + ///Legacy Ruby. Determines if a record exists already in the record collection + internal class func update_or_create(_ data: CDAKRecord) -> CDAKRecord { + //existing = CDAKRecord.where(medical_record_number: data.medical_record_number).first + var existing: CDAKRecord? + for record in CDAKGlobals.sharedInstance.CDAKRecords { + if record.medical_record_number == data.medical_record_number { + existing = record + } + } + if var existing = existing { + //FIX_ME: this is just horribly dangerous + //kludgy (and probably wrong) work-around for Ruby's being able to just magically copy + //existing.update_attributes!(data.attributes.except('_id')) + existing = data.copy() as! CDAKRecord + return existing + } else { + return data + } + } + + ///Legacy Ruby. Returns all providers contained in provider performances + internal func providers() -> [CDAKProvider] { + return provider_performances.filter({pp in pp.provider != nil}).map({pp in pp.provider!}) + } ///returns a specific set of patient entry records based on the supplied section name (if found) @@ -713,7 +713,7 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } } - /* + fileprivate class func provider_queries(_ provider_id: String, effective_date: Double) -> CDAKProvider? { //FIX_ME: - review implementation for accuracy //Making the (probably bad) assumption these return a single value - provider_id assumed to be unique @@ -746,7 +746,7 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } return nil } - */ + // MARK: - Initializers required override public init() { // <== Need "required" because we need to call dynamicType() below @@ -859,10 +859,10 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { // MARK: Standard properties ///Debugging description - /********** + override open var description : String { return "CDAKRecord => prefix: \(prefix), first: \(first), last: \(last), suffix: \(suffix), gender: \(gender), birthdate: \(birthdate), deathdate: \(deathdate), religious_affiliation: \(religious_affiliation), effective_time: \(effective_time), race: \(race), ethnicity: \(ethnicity), languages = \(languages), marital_status: \(marital_status), medical_record_number: \(medical_record_number), medical_record_assigner: \(medical_record_assigner), expired: \(expired), clinicalTrialParticipant: \(clinicalTrialParticipant), allergies: \(allergies), care_goals: \(care_goals), conditions: \(conditions), encounters: \(encounters), communications: \(communications), family_history: \(family_history), immunizations: \(immunizations), medical_equipment: \(medical_equipment), medications: \(medications), procedures: \(procedures), results: \(results), social_history: \(social_history), vital_signs: \(vital_signs), advance_directives: \(advance_directives), insurance_providers: \(insurance_providers), functional_statuses: \(functional_statuses), provider_performances: \(provider_performances), addresses: \(addresses), telecoms: \(telecoms)" } - ********/ + } From be63450b83297b827eebbc7ca48bb4178fe8c68e Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Sun, 30 Oct 2016 18:09:07 -0400 Subject: [PATCH 10/15] Re-combine record*.swift to record.swift now that the Swift compiler bug failure with record.swift is resolved. --- CDAKit.xcodeproj/project.pbxproj | 12 - .../lib/models/record.swift | 293 ++++++++++++++++++ .../lib/models/record1.swift | 107 ------- .../lib/models/record2.swift | 70 ----- .../lib/models/record3.swift | 113 ------- 5 files changed, 293 insertions(+), 302 deletions(-) diff --git a/CDAKit.xcodeproj/project.pbxproj b/CDAKit.xcodeproj/project.pbxproj index c95a81f..66d67f9 100644 --- a/CDAKit.xcodeproj/project.pbxproj +++ b/CDAKit.xcodeproj/project.pbxproj @@ -14,8 +14,6 @@ 38359E0A1C7B774400CCC036 /* CDAKit.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 38359E071C7B774400CCC036 /* CDAKit.podspec */; }; 38359E0B1C7B774400CCC036 /* LICENSE.txt in Resources */ = {isa = PBXBuildFile; fileRef = 38359E081C7B774400CCC036 /* LICENSE.txt */; }; 38359E0C1C7B774400CCC036 /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = 38359E091C7B774400CCC036 /* Podfile */; }; - 3845045B1DBFABB500FA7A27 /* record2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3845045A1DBFABB500FA7A27 /* record2.swift */; }; - 3845045D1DBFABC700FA7A27 /* record3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3845045C1DBFABC600FA7A27 /* record3.swift */; }; 384E23111C737A8C009B9DED /* 170.314(b)(1)InPt_Discharge Summary CED Type.xml in Resources */ = {isa = PBXBuildFile; fileRef = 384E23101C737A8C009B9DED /* 170.314(b)(1)InPt_Discharge Summary CED Type.xml */; }; 384E23141C738E4E009B9DED /* CDAKJSONInstantiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384E23131C738E4E009B9DED /* CDAKJSONInstantiable.swift */; }; 384E23171C73C517009B9DED /* MetadataImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384E23161C73C517009B9DED /* MetadataImporter.swift */; }; @@ -303,7 +301,6 @@ 38BE32B81C80F5EB002AEC25 /* cda_social_history_importer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38BE32B71C80F5EB002AEC25 /* cda_social_history_importer.swift */; }; 38BE32BA1C80F7A9002AEC25 /* ccda_medication_importer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38BE32B91C80F7A9002AEC25 /* ccda_medication_importer.swift */; }; 38BE32BC1C81002F002AEC25 /* c32_provider_performer.c32.mustache in Resources */ = {isa = PBXBuildFile; fileRef = 38BE32BB1C81002F002AEC25 /* c32_provider_performer.c32.mustache */; }; - 38C30C061DBFA6D5009652B8 /* record1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38C30C051DBFA6D5009652B8 /* record1.swift */; }; 38CB596B1C8720D4004630F9 /* ccda_code_without_reference.ccda.mustache in Resources */ = {isa = PBXBuildFile; fileRef = 38CB596A1C8720D4004630F9 /* ccda_code_without_reference.ccda.mustache */; }; 38CB596D1C8731BD004630F9 /* ccda_medication_dose.ccda.mustache in Resources */ = {isa = PBXBuildFile; fileRef = 38CB596C1C8731BD004630F9 /* ccda_medication_dose.ccda.mustache */; }; 38CB596F1C8736B0004630F9 /* ccda_medication_admin_timing.ccda.mustache in Resources */ = {isa = PBXBuildFile; fileRef = 38CB596E1C8736B0004630F9 /* ccda_medication_admin_timing.ccda.mustache */; }; @@ -338,8 +335,6 @@ 38359E071C7B774400CCC036 /* CDAKit.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CDAKit.podspec; sourceTree = ""; }; 38359E081C7B774400CCC036 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; 38359E091C7B774400CCC036 /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 3845045A1DBFABB500FA7A27 /* record2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = record2.swift; sourceTree = ""; }; - 3845045C1DBFABC600FA7A27 /* record3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = record3.swift; sourceTree = ""; }; 384E23101C737A8C009B9DED /* 170.314(b)(1)InPt_Discharge Summary CED Type.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "170.314(b)(1)InPt_Discharge Summary CED Type.xml"; sourceTree = ""; }; 384E23131C738E4E009B9DED /* CDAKJSONInstantiable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CDAKJSONInstantiable.swift; sourceTree = ""; }; 384E23161C73C517009B9DED /* MetadataImporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetadataImporter.swift; sourceTree = ""; }; @@ -631,7 +626,6 @@ 38BE32B71C80F5EB002AEC25 /* cda_social_history_importer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = cda_social_history_importer.swift; sourceTree = ""; }; 38BE32B91C80F7A9002AEC25 /* ccda_medication_importer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ccda_medication_importer.swift; sourceTree = ""; }; 38BE32BB1C81002F002AEC25 /* c32_provider_performer.c32.mustache */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = c32_provider_performer.c32.mustache; sourceTree = ""; }; - 38C30C051DBFA6D5009652B8 /* record1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = record1.swift; sourceTree = ""; }; 38CB596A1C8720D4004630F9 /* ccda_code_without_reference.ccda.mustache */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ccda_code_without_reference.ccda.mustache; sourceTree = ""; }; 38CB596C1C8731BD004630F9 /* ccda_medication_dose.ccda.mustache */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ccda_medication_dose.ccda.mustache; sourceTree = ""; }; 38CB596E1C8736B0004630F9 /* ccda_medication_admin_timing.ccda.mustache */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ccda_medication_admin_timing.ccda.mustache; sourceTree = ""; }; @@ -1008,9 +1002,6 @@ 389170881C6CD7C800A31299 /* provider.swift */, 389170891C6CD7C800A31299 /* reason.swift */, 3891708A1C6CD7C800A31299 /* record.swift */, - 38C30C051DBFA6D5009652B8 /* record1.swift */, - 3845045A1DBFABB500FA7A27 /* record2.swift */, - 3845045C1DBFABC600FA7A27 /* record3.swift */, 3891708B1C6CD7C800A31299 /* reference.swift */, 3891708C1C6CD7C800A31299 /* result_value.swift */, 3891708D1C6CD7C800A31299 /* social_history.swift */, @@ -1752,15 +1743,12 @@ 389170AB1C6CD7C800A31299 /* person.swift in Sources */, 389171091C6CD88A00A31299 /* ccda_vital_sign_importer.swift in Sources */, 389170EE1C6CD86D00A31299 /* cda_provider_importer.swift in Sources */, - 38C30C061DBFA6D5009652B8 /* record1.swift in Sources */, 384E23221C73C7A2009B9DED /* CDAKQRDAHeader.swift in Sources */, - 3845045B1DBFABB500FA7A27 /* record2.swift in Sources */, 389171021C6CD88A00A31299 /* ccda_immunization_importer.swift in Sources */, 384E23201C73C797009B9DED /* CDAKQRDADevice.swift in Sources */, 389170A51C6CD7C800A31299 /* insurance_provider.swift in Sources */, 3891711B1C6CD8A500A31299 /* CDAKValueAndUnit.swift in Sources */, 389170C51C6CD81900A31299 /* HDSExport.swift in Sources */, - 3845045D1DBFABC700FA7A27 /* record3.swift in Sources */, 384E23241C73C7CE009B9DED /* CDAKQRDALegalAuthenticator.swift in Sources */, 389170A11C6CD7C800A31299 /* fulfillment_history.swift in Sources */, 389170C61C6CD81900A31299 /* template_helper.swift in Sources */, diff --git a/CDAKit/health-data-standards/lib/models/record.swift b/CDAKit/health-data-standards/lib/models/record.swift index 67bec43..507beab 100644 --- a/CDAKit/health-data-standards/lib/models/record.swift +++ b/CDAKit/health-data-standards/lib/models/record.swift @@ -866,3 +866,296 @@ open class CDAKRecord: NSObject, NSCopying, CDAKPropertyAddressable { } + +extension CDAKRecord { + + // MARK: - Mustache marshalling + override open var mustacheBox: MustacheBox { + + //var vals: [String:MustacheBox] = [:] // [String:MustacheBox]() + var defaultLanguage: CDAKCodedEntries = CDAKCodedEntries() + defaultLanguage.addCodes("IETF", code: "en-US") + let defaultLanguages: [CDAKCodedEntries] = [defaultLanguage] + + var vals: [String:MustacheBox] = [ + "id": Box(self._id), + "prefix": Box(self.prefix), + "first": Box(self.first), + "last": Box(self.last), + "suffix": Box(self.suffix), + "gender": Box(self.gender), + "birthdate": Box(self.birthdate), + "deathdate": Box(self.deathdate), + "religious_affiliation": Box(self.religious_affiliation), + "effective_time": Box(self.effective_time), + "race": Box(self.race), + "ethnicity": Box(self.ethnicity), + "languages": self.languages.count > 0 ? Box(self.languages) : Box(defaultLanguages), + "marital_status": Box(self.marital_status), + "medical_record_number": Box(self.medical_record_number), + "medical_record_assigner": Box(self.medical_record_assigner), + "expired": Box(self.expired), + "addresses": Box(self.addresses), + "telecoms": Box(self.telecoms) + ] + + if identifiers.count > 0 { + vals["identifiers"] = Box(self.identifiers) + } + + + // we can't pass locals into mustache like we can with erb, so we're cheating + // when we marshall the data, we're setting up template block values here instead + // you can use template values from here + /* + key, section, entries, status, value + */ + if let entries = boxEntries(allergies, section: "allergies") { + vals["allergies"] = entries + } + if let entries = boxEntries(results, section: "results", value: true) { + vals["results"] = entries + } + if let entries = boxEntries(medications, section: "medications") { + vals["medications"] = entries + } + if let entries = boxEntries(care_goals, section: "plan_of_care") { + vals["care_goals"] = entries + } + if let entries = boxEntries(conditions, section: "conditions", status: true) { + vals["conditions"] = entries + } + if let entries = boxEntries(social_history, section: "social_history") { + vals["social_history"] = entries + } + if let entries = boxEntries(immunizations, section: "immunizations") { + vals["immunizations"] = entries + } + if let entries = boxEntries(medical_equipment, section: "medical_equipment") { + vals["medical_equipment"] = entries + } + if let entries = boxEntries(encounters, section: "encounters") { + vals["encounters"] = entries + } + if let entries = boxEntries(procedures, section: "procedures") { + vals["procedures"] = entries + } + if let entries = boxEntries(vital_signs, section: "vitals", value: true) { + vals["vital_signs"] = entries + } + + if let header = header { + vals["header"] = Box(header) + } + + if provider_performances.count > 0 { + vals["provider_performances"] = Box(provider_performances) + } + + + return Box(vals) + } + + func boxEntries(_ entries: [CDAKEntry], section: String, status: Bool = false, value: Bool = false) -> MustacheBox? { + + if entries.count > 0 { + + let toBox = [ + "section" : Box(section), + "status" : Box(status), + "value" : Box(value), + "entries": Box(entries) + ] + + return Box(toBox) + } + + return nil + } + +} + + +extension CDAKRecord { + //MARK: Primary CDA import / export Methods + /** + Master public convenience method for exporting record to CDA + + Formats defined in: CDAKExport.CDAKExportFormat + + EX: .ccda or .c32 + + */ + public func export(inFormat format: CDAKExport.CDAKExportFormat) -> String { + return CDAKExport.export(patientRecord: self, inFormat: format) + } + + /** + Creates a new record from CDA XML + */ + public convenience init(fromXML doc: String) throws { + let x = try CDAKImport_BulkRecordImporter.importRecord(doc) + self.init(copyFrom: x) + } + + //MARK: Convenience copying + public convenience init(copyFrom record: CDAKRecord) { + self.init() + + self.prefix = record.prefix + self.first = record.first + self.last = record.last + self.suffix = record.suffix + self.gender = record.gender + self.birthdate = record.birthdate + self.deathdate = record.deathdate + self.religious_affiliation = record.religious_affiliation + self.effective_time = record.effective_time + self.race = record.race + self.ethnicity = record.ethnicity + self.languages = record.languages + self.marital_status = record.marital_status + self.medical_record_number = record.medical_record_number + self.medical_record_assigner = record.medical_record_assigner + self.expired = record.expired + self.allergies = record.allergies + self.care_goals = record.care_goals + self.conditions = record.conditions + self.encounters = record.encounters + self.communications = record.communications + self.family_history = record.family_history + self.immunizations = record.immunizations + self.medical_equipment = record.medical_equipment + self.medications = record.medications + self.procedures = record.procedures + self.results = record.results + self.socialhistories = record.socialhistories + self.vital_signs = record.vital_signs + self.support = record.support + self.advance_directives = record.advance_directives + self.insurance_providers = record.insurance_providers + self.functional_statuses = record.functional_statuses + self.provider_performances = record.provider_performances + self.addresses = record.addresses + self.telecoms = record.telecoms + self.identifiers = record.identifiers + self.custodian = record.custodian + self.clinicalTrialParticipant = record.clinicalTrialParticipant + } + + +} + +extension CDAKRecord: CDAKJSONExportable { + // MARK: - JSON Generation + ///Dictionary for JSON data + + //public var jsonDict: [String: AnyObject] = [:] + + + public var jsonDict: [String: AnyObject] { + var dict: [String: AnyObject] = [:] + + if identifiers.count > 0 { + dict["identifiers"] = identifiers.map({$0.jsonDict}) as AnyObject? + } + + if let prefix = prefix { + dict["prefix"] = prefix as AnyObject? + } + if let first = first { + dict["first"] = first as AnyObject? + } + if let last = last { + dict["last"] = last as AnyObject? + } + if let suffix = suffix { + dict["suffix"] = suffix as AnyObject? + } + if let gender = gender { + dict["gender"] = gender as AnyObject? + } + if let birthdate = birthdate { + dict["birthdate"] = birthdate as AnyObject? + } + if let deathdate = deathdate { + dict["deathdate"] = deathdate as AnyObject? + } + + if religious_affiliation.count > 0 { + dict["religious_affiliation"] = religious_affiliation.codes.map({$0.jsonDict}) as AnyObject? + } + + if let effective_time = effective_time { + dict["effective_time"] = effective_time as AnyObject? + } + + dict["id"] = _id as AnyObject? + + if let header = header { + dict["header"] = header.jsonDict as AnyObject? + } + + if pregnancies.count > 0 { + dict["pregnancies"] = pregnancies.map({$0.jsonDict}) as AnyObject? + } + if race.count > 0 { + dict["race"] = race.codes.map({$0.jsonDict}) as AnyObject? + } + if ethnicity.count > 0 { + dict["ethnicity"] = ethnicity.codes.map({$0.jsonDict}) as AnyObject? + } + + if languages.count > 0 { + dict["languages"] = languages.map({$0.jsonDict}) as AnyObject? + } + + if marital_status.count > 0 { + dict["marital_status"] = marital_status.codes.map({$0.jsonDict}) as AnyObject? + } + + if let medical_record_number = medical_record_number { + dict["medical_record_number"] = medical_record_number as AnyObject? + } + + if let medical_record_assigner = medical_record_assigner { + dict["medical_record_assigner"] = medical_record_assigner as AnyObject? + } + + if let expired = expired { + dict["expired"] = expired as AnyObject? + } + + if let clinicalTrialParticipant = clinicalTrialParticipant { + dict["clinicalTrialParticipant"] = clinicalTrialParticipant as AnyObject? + } + + if let custodian = custodian { + dict["custodian"] = custodian as AnyObject? + } + + if allergies.count > 0 { dict["allergies"] = allergies.map({$0.jsonDict}) as AnyObject? } + if care_goals.count > 0 { dict["care_goals"] = care_goals.map({$0.jsonDict}) as AnyObject?} + if conditions.count > 0 { dict["conditions"] = conditions.map({$0.jsonDict}) as AnyObject? } + if encounters.count > 0 { dict["encounters"] = encounters.map({$0.jsonDict}) as AnyObject? } + if communications.count > 0 { dict["communications"] = communications.map({$0.jsonDict}) as AnyObject? } + if family_history.count > 0 { dict["family_history"] = family_history.map({$0.jsonDict}) as AnyObject? } + if immunizations.count > 0 { dict["immunizations"] = immunizations.map({$0.jsonDict}) as AnyObject? } + if medical_equipment.count > 0 { dict["medical_equipment"] = medical_equipment.map({$0.jsonDict}) as AnyObject?} + if medications.count > 0 { dict["medications"] = medications.map({$0.jsonDict}) as AnyObject? } + if procedures.count > 0 { dict["procedures"] = procedures.map({$0.jsonDict}) as AnyObject? } + if results.count > 0 { dict["results"] = results.map({$0.jsonDict}) as AnyObject? } + if social_history.count > 0 { dict["social_history"] = social_history.map({$0.jsonDict}) as AnyObject? } + if vital_signs.count > 0 { dict["vital_signs"] = vital_signs.map({$0.jsonDict}) as AnyObject? } + if support.count > 0 { dict["support"] = support.map({$0.jsonDict}) as AnyObject? } + if advance_directives.count > 0 { dict["advance_directives"] = advance_directives.map({$0.jsonDict}) as AnyObject? } + if insurance_providers.count > 0 { dict["insurance_providers"] = insurance_providers.map({$0.jsonDict}) as AnyObject?} + if functional_statuses.count > 0 { dict["functional_statuses"] = functional_statuses.map({$0.jsonDict}) as AnyObject?} + if provider_performances.count > 0 { dict["provider_performances"] = provider_performances.map({$0.jsonDict}) as AnyObject?} + if addresses.count > 0 { dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } + if telecoms.count > 0 { dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject?} + + + return dict + } +} diff --git a/CDAKit/health-data-standards/lib/models/record1.swift b/CDAKit/health-data-standards/lib/models/record1.swift index 7d1c4a9..b7ac162 100644 --- a/CDAKit/health-data-standards/lib/models/record1.swift +++ b/CDAKit/health-data-standards/lib/models/record1.swift @@ -10,113 +10,6 @@ import Foundation import Mustache -extension CDAKRecord { - - // MARK: - Mustache marshalling - override open var mustacheBox: MustacheBox { - - //var vals: [String:MustacheBox] = [:] // [String:MustacheBox]() - var defaultLanguage: CDAKCodedEntries = CDAKCodedEntries() - defaultLanguage.addCodes("IETF", code: "en-US") - let defaultLanguages: [CDAKCodedEntries] = [defaultLanguage] - - var vals: [String:MustacheBox] = [ - "id": Box(self._id), - "prefix": Box(self.prefix), - "first": Box(self.first), - "last": Box(self.last), - "suffix": Box(self.suffix), - "gender": Box(self.gender), - "birthdate": Box(self.birthdate), - "deathdate": Box(self.deathdate), - "religious_affiliation": Box(self.religious_affiliation), - "effective_time": Box(self.effective_time), - "race": Box(self.race), - "ethnicity": Box(self.ethnicity), - "languages": self.languages.count > 0 ? Box(self.languages) : Box(defaultLanguages), - "marital_status": Box(self.marital_status), - "medical_record_number": Box(self.medical_record_number), - "medical_record_assigner": Box(self.medical_record_assigner), - "expired": Box(self.expired), - "addresses": Box(self.addresses), - "telecoms": Box(self.telecoms) - ] - - if identifiers.count > 0 { - vals["identifiers"] = Box(self.identifiers) - } - - - // we can't pass locals into mustache like we can with erb, so we're cheating - // when we marshall the data, we're setting up template block values here instead - // you can use template values from here - /* - key, section, entries, status, value - */ - if let entries = boxEntries(allergies, section: "allergies") { - vals["allergies"] = entries - } - if let entries = boxEntries(results, section: "results", value: true) { - vals["results"] = entries - } - if let entries = boxEntries(medications, section: "medications") { - vals["medications"] = entries - } - if let entries = boxEntries(care_goals, section: "plan_of_care") { - vals["care_goals"] = entries - } - if let entries = boxEntries(conditions, section: "conditions", status: true) { - vals["conditions"] = entries - } - if let entries = boxEntries(social_history, section: "social_history") { - vals["social_history"] = entries - } - if let entries = boxEntries(immunizations, section: "immunizations") { - vals["immunizations"] = entries - } - if let entries = boxEntries(medical_equipment, section: "medical_equipment") { - vals["medical_equipment"] = entries - } - if let entries = boxEntries(encounters, section: "encounters") { - vals["encounters"] = entries - } - if let entries = boxEntries(procedures, section: "procedures") { - vals["procedures"] = entries - } - if let entries = boxEntries(vital_signs, section: "vitals", value: true) { - vals["vital_signs"] = entries - } - - if let header = header { - vals["header"] = Box(header) - } - - if provider_performances.count > 0 { - vals["provider_performances"] = Box(provider_performances) - } - - - return Box(vals) - } - - func boxEntries(_ entries: [CDAKEntry], section: String, status: Bool = false, value: Bool = false) -> MustacheBox? { - - if entries.count > 0 { - - let toBox = [ - "section" : Box(section), - "status" : Box(status), - "value" : Box(value), - "entries": Box(entries) - ] - - return Box(toBox) - } - - return nil - } - -} diff --git a/CDAKit/health-data-standards/lib/models/record2.swift b/CDAKit/health-data-standards/lib/models/record2.swift index a827788..29c683e 100644 --- a/CDAKit/health-data-standards/lib/models/record2.swift +++ b/CDAKit/health-data-standards/lib/models/record2.swift @@ -8,73 +8,3 @@ import Foundation - -extension CDAKRecord { - //MARK: Primary CDA import / export Methods - /** - Master public convenience method for exporting record to CDA - - Formats defined in: CDAKExport.CDAKExportFormat - - EX: .ccda or .c32 - - */ - public func export(inFormat format: CDAKExport.CDAKExportFormat) -> String { - return CDAKExport.export(patientRecord: self, inFormat: format) - } - - /** - Creates a new record from CDA XML - */ - public convenience init(fromXML doc: String) throws { - let x = try CDAKImport_BulkRecordImporter.importRecord(doc) - self.init(copyFrom: x) - } - - //MARK: Convenience copying - public convenience init(copyFrom record: CDAKRecord) { - self.init() - - self.prefix = record.prefix - self.first = record.first - self.last = record.last - self.suffix = record.suffix - self.gender = record.gender - self.birthdate = record.birthdate - self.deathdate = record.deathdate - self.religious_affiliation = record.religious_affiliation - self.effective_time = record.effective_time - self.race = record.race - self.ethnicity = record.ethnicity - self.languages = record.languages - self.marital_status = record.marital_status - self.medical_record_number = record.medical_record_number - self.medical_record_assigner = record.medical_record_assigner - self.expired = record.expired - self.allergies = record.allergies - self.care_goals = record.care_goals - self.conditions = record.conditions - self.encounters = record.encounters - self.communications = record.communications - self.family_history = record.family_history - self.immunizations = record.immunizations - self.medical_equipment = record.medical_equipment - self.medications = record.medications - self.procedures = record.procedures - self.results = record.results - self.socialhistories = record.socialhistories - self.vital_signs = record.vital_signs - self.support = record.support - self.advance_directives = record.advance_directives - self.insurance_providers = record.insurance_providers - self.functional_statuses = record.functional_statuses - self.provider_performances = record.provider_performances - self.addresses = record.addresses - self.telecoms = record.telecoms - self.identifiers = record.identifiers - self.custodian = record.custodian - self.clinicalTrialParticipant = record.clinicalTrialParticipant - } - - -} diff --git a/CDAKit/health-data-standards/lib/models/record3.swift b/CDAKit/health-data-standards/lib/models/record3.swift index 6156ba1..50de7d7 100644 --- a/CDAKit/health-data-standards/lib/models/record3.swift +++ b/CDAKit/health-data-standards/lib/models/record3.swift @@ -8,116 +8,3 @@ import Foundation -extension CDAKRecord: CDAKJSONExportable { - // MARK: - JSON Generation - ///Dictionary for JSON data - - //public var jsonDict: [String: AnyObject] = [:] - - - public var jsonDict: [String: AnyObject] { - var dict: [String: AnyObject] = [:] - - if identifiers.count > 0 { - dict["identifiers"] = identifiers.map({$0.jsonDict}) as AnyObject? - } - - if let prefix = prefix { - dict["prefix"] = prefix as AnyObject? - } - if let first = first { - dict["first"] = first as AnyObject? - } - if let last = last { - dict["last"] = last as AnyObject? - } - if let suffix = suffix { - dict["suffix"] = suffix as AnyObject? - } - if let gender = gender { - dict["gender"] = gender as AnyObject? - } - if let birthdate = birthdate { - dict["birthdate"] = birthdate as AnyObject? - } - if let deathdate = deathdate { - dict["deathdate"] = deathdate as AnyObject? - } - - if religious_affiliation.count > 0 { - dict["religious_affiliation"] = religious_affiliation.codes.map({$0.jsonDict}) as AnyObject? - } - - if let effective_time = effective_time { - dict["effective_time"] = effective_time as AnyObject? - } - - dict["id"] = _id as AnyObject? - - if let header = header { - dict["header"] = header.jsonDict as AnyObject? - } - - if pregnancies.count > 0 { - dict["pregnancies"] = pregnancies.map({$0.jsonDict}) as AnyObject? - } - if race.count > 0 { - dict["race"] = race.codes.map({$0.jsonDict}) as AnyObject? - } - if ethnicity.count > 0 { - dict["ethnicity"] = ethnicity.codes.map({$0.jsonDict}) as AnyObject? - } - - if languages.count > 0 { - dict["languages"] = languages.map({$0.jsonDict}) as AnyObject? - } - - if marital_status.count > 0 { - dict["marital_status"] = marital_status.codes.map({$0.jsonDict}) as AnyObject? - } - - if let medical_record_number = medical_record_number { - dict["medical_record_number"] = medical_record_number as AnyObject? - } - - if let medical_record_assigner = medical_record_assigner { - dict["medical_record_assigner"] = medical_record_assigner as AnyObject? - } - - if let expired = expired { - dict["expired"] = expired as AnyObject? - } - - if let clinicalTrialParticipant = clinicalTrialParticipant { - dict["clinicalTrialParticipant"] = clinicalTrialParticipant as AnyObject? - } - - if let custodian = custodian { - dict["custodian"] = custodian as AnyObject? - } - - if allergies.count > 0 { dict["allergies"] = allergies.map({$0.jsonDict}) as AnyObject? } - if care_goals.count > 0 { dict["care_goals"] = care_goals.map({$0.jsonDict}) as AnyObject?} - if conditions.count > 0 { dict["conditions"] = conditions.map({$0.jsonDict}) as AnyObject? } - if encounters.count > 0 { dict["encounters"] = encounters.map({$0.jsonDict}) as AnyObject? } - if communications.count > 0 { dict["communications"] = communications.map({$0.jsonDict}) as AnyObject? } - if family_history.count > 0 { dict["family_history"] = family_history.map({$0.jsonDict}) as AnyObject? } - if immunizations.count > 0 { dict["immunizations"] = immunizations.map({$0.jsonDict}) as AnyObject? } - if medical_equipment.count > 0 { dict["medical_equipment"] = medical_equipment.map({$0.jsonDict}) as AnyObject?} - if medications.count > 0 { dict["medications"] = medications.map({$0.jsonDict}) as AnyObject? } - if procedures.count > 0 { dict["procedures"] = procedures.map({$0.jsonDict}) as AnyObject? } - if results.count > 0 { dict["results"] = results.map({$0.jsonDict}) as AnyObject? } - if social_history.count > 0 { dict["social_history"] = social_history.map({$0.jsonDict}) as AnyObject? } - if vital_signs.count > 0 { dict["vital_signs"] = vital_signs.map({$0.jsonDict}) as AnyObject? } - if support.count > 0 { dict["support"] = support.map({$0.jsonDict}) as AnyObject? } - if advance_directives.count > 0 { dict["advance_directives"] = advance_directives.map({$0.jsonDict}) as AnyObject? } - if insurance_providers.count > 0 { dict["insurance_providers"] = insurance_providers.map({$0.jsonDict}) as AnyObject?} - if functional_statuses.count > 0 { dict["functional_statuses"] = functional_statuses.map({$0.jsonDict}) as AnyObject?} - if provider_performances.count > 0 { dict["provider_performances"] = provider_performances.map({$0.jsonDict}) as AnyObject?} - if addresses.count > 0 { dict["addresses"] = addresses.map({$0.jsonDict}) as AnyObject? } - if telecoms.count > 0 { dict["telecoms"] = telecoms.map({$0.jsonDict}) as AnyObject?} - - - return dict - } -} From 6e160924b51fae2a5e52c4e7725b31760066c487 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Sun, 30 Oct 2016 18:28:32 -0400 Subject: [PATCH 11/15] Updated version to 1.1.0, updated pod spec, README.md, release-notes.md --- CDAKit.podspec | 2 +- README.md | 8 ++++---- release-notes.md | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CDAKit.podspec b/CDAKit.podspec index be8ef49..ef0dcff 100755 --- a/CDAKit.podspec +++ b/CDAKit.podspec @@ -6,7 +6,7 @@ Pod::Spec.new do |s| s.name = "CDAKit" - s.version = "1.0.2" + s.version = "1.1.0" s.summary = "CDAKit for iOS, the Open Source Clinical Document Architecture Library with HealthKit Connectivity." s.description = <<-DESC Swift framework port of the the Ruby Health-Data-Standards GEM's C32 and C-CDA import and export functionality. Allows for bridging between CDA and HealthKit so you can integrate with an Electronic Medical Records system. diff --git a/README.md b/README.md index 8010967..a6ca9b9 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ * CDAKit GitHub - [Source](https://github.com/ewhitley/CDAKit) * Additional [documentation](https://ewhitley.github.io/CDAKit) -* Current Version: 1.0.2. [Revision History](https://github.com/ewhitley/CDAKit/blob/master/release-notes.md) +* Current Version: 1.1.0. [Revision History](https://github.com/ewhitley/CDAKit/blob/master/release-notes.md) CDAKit provides C32 and C-CDA import and export functionality as well as the ability to connect CDA concepts with HealthKit samples. This allows for bridging between CDA and HealthKit so you can integrate with an Electronic Medical Records system. @@ -111,8 +111,8 @@ catch { ## Requirements - iOS 8+ -- Xcode 7 -- Swift 2.1 +- Xcode 8+ +- Swift 3 ## Using CocoaPods @@ -124,7 +124,7 @@ platform :ios, '8.0' use_frameworks! target 'MyApp' do -pod 'CDAKit', '~> 1.0' +pod 'CDAKit', '~> 1.1' end ``` diff --git a/release-notes.md b/release-notes.md index 884d004..12f46b4 100644 --- a/release-notes.md +++ b/release-notes.md @@ -2,10 +2,11 @@ * **1.0**: Initial release * **1.0.2**: Enhancements to providers, encounters, and medications +* **1.1.0**: Updated to XCode 8, Swift 3 -#1.0.2 +#1.1.0 -[Commits](https://github.com/ewhitley/CDAKit/compare/1.0...1.0.2) +[Commits](https://github.com/ewhitley/CDAKit/compare/1.0...1.1.0) ##Changes From 6794e2f6e1482fa97fbc493bc1f58b101c46dc87 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Sun, 30 Oct 2016 19:26:02 -0400 Subject: [PATCH 12/15] The pod Try now has finally been updated to work with Xcode 8 and Swift 3 (Version 2.0.0). So restoring that back in, removing local copies. Now all three pods: GRMustache.swift, Fuzi, and Try have release updates supporting Xcode 8 and Swift 3. --- CDAKit.xcodeproj/project.pbxproj | 12 ------------ CDAKit/CDAKit.h | 3 +-- CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift | 2 +- Podfile | 2 ++ 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/CDAKit.xcodeproj/project.pbxproj b/CDAKit.xcodeproj/project.pbxproj index 66d67f9..34b3545 100644 --- a/CDAKit.xcodeproj/project.pbxproj +++ b/CDAKit.xcodeproj/project.pbxproj @@ -291,9 +291,6 @@ 389172F91C6CFD9100A31299 /* risk_category_assessment_fragment.xml in Resources */ = {isa = PBXBuildFile; fileRef = 389172CF1C6CFD9000A31299 /* risk_category_assessment_fragment.xml */; }; 389172FA1C6CFD9100A31299 /* symptom_active_fragment.xml in Resources */ = {isa = PBXBuildFile; fileRef = 389172D01C6CFD9000A31299 /* symptom_active_fragment.xml */; }; 389172FB1C6CFD9100A31299 /* tobacco_use_fragment.xml in Resources */ = {isa = PBXBuildFile; fileRef = 389172D11C6CFD9000A31299 /* tobacco_use_fragment.xml */; }; - 38B938261DBE8BC30013DCD0 /* trap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38B938231DBE8BC30013DCD0 /* trap.swift */; }; - 38B938271DBE8BC30013DCD0 /* WBTry.h in Headers */ = {isa = PBXBuildFile; fileRef = 38B938241DBE8BC30013DCD0 /* WBTry.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 38B938281DBE8BC30013DCD0 /* WBTry.m in Sources */ = {isa = PBXBuildFile; fileRef = 38B938251DBE8BC30013DCD0 /* WBTry.m */; }; 38BC98131C7C9F3400E8F2F4 /* CDAKRecordModels_Common.png in Resources */ = {isa = PBXBuildFile; fileRef = 38BC98121C7C9F3400E8F2F4 /* CDAKRecordModels_Common.png */; }; 38BC98151C7C9F5600E8F2F4 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 38BC98141C7C9F5600E8F2F4 /* README.md */; }; 38BC98191C7CF19D00E8F2F4 /* CDAKitGithubLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = 38BC98181C7CF19D00E8F2F4 /* CDAKitGithubLogo.png */; }; @@ -616,9 +613,6 @@ 389172CF1C6CFD9000A31299 /* risk_category_assessment_fragment.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = risk_category_assessment_fragment.xml; sourceTree = ""; }; 389172D01C6CFD9000A31299 /* symptom_active_fragment.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = symptom_active_fragment.xml; sourceTree = ""; }; 389172D11C6CFD9000A31299 /* tobacco_use_fragment.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = tobacco_use_fragment.xml; sourceTree = ""; }; - 38B938231DBE8BC30013DCD0 /* trap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = trap.swift; sourceTree = ""; }; - 38B938241DBE8BC30013DCD0 /* WBTry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBTry.h; sourceTree = ""; }; - 38B938251DBE8BC30013DCD0 /* WBTry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBTry.m; sourceTree = ""; }; 38BC98121C7C9F3400E8F2F4 /* CDAKRecordModels_Common.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CDAKRecordModels_Common.png; sourceTree = ""; }; 38BC98141C7C9F5600E8F2F4 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 38BC98181C7CF19D00E8F2F4 /* CDAKitGithubLogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CDAKitGithubLogo.png; sourceTree = ""; }; @@ -959,9 +953,6 @@ 389170BE1C6CD7FF00A31299 /* code_system_helper.swift */, 380A41081C77AECF00E5D7B8 /* CDAKVocabularyStructs.swift */, 389170BF1C6CD7FF00A31299 /* hl7_helper.swift */, - 38B938231DBE8BC30013DCD0 /* trap.swift */, - 38B938241DBE8BC30013DCD0 /* WBTry.h */, - 38B938251DBE8BC30013DCD0 /* WBTry.m */, ); path = util; sourceTree = ""; @@ -1347,7 +1338,6 @@ buildActionMask = 2147483647; files = ( 389170351C6CC1EE00A31299 /* CDAKit.h in Headers */, - 38B938271DBE8BC30013DCD0 /* WBTry.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1689,7 +1679,6 @@ 389170C11C6CD7FF00A31299 /* hl7_helper.swift in Sources */, 389170BA1C6CD7C800A31299 /* thing_with_times.swift in Sources */, 389170B71C6CD7C800A31299 /* support.swift in Sources */, - 38B938261DBE8BC30013DCD0 /* trap.swift in Sources */, 3891706B1C6CD7A500A31299 /* pedigree.swift in Sources */, 389171181C6CD8A500A31299 /* Dictionary+Extensions.swift in Sources */, 389170B91C6CD7C800A31299 /* thing_with_codes.swift in Sources */, @@ -1777,7 +1766,6 @@ 3891711F1C6CD8A500A31299 /* String+CryptoExtensions.swift in Sources */, 389171031C6CD88A00A31299 /* ccda_insurance_provider_importer.swift in Sources */, 389170B31C6CD7C800A31299 /* record.swift in Sources */, - 38B938281DBE8BC30013DCD0 /* WBTry.m in Sources */, 389170E41C6CD86D00A31299 /* cda_allergy_importer.swift in Sources */, 389170A81C6CD7C800A31299 /* medication.swift in Sources */, 389170611C6CD74500A31299 /* CDAKitHealthKitBridge.swift in Sources */, diff --git a/CDAKit/CDAKit.h b/CDAKit/CDAKit.h index f530c02..8272343 100644 --- a/CDAKit/CDAKit.h +++ b/CDAKit/CDAKit.h @@ -7,8 +7,7 @@ // #import -//#import -#import "WBTry.h" +#import //! Project version number for CDAKit. FOUNDATION_EXPORT double CDAKitVersionNumber; diff --git a/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift b/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift index 28d1d68..2b10b9b 100644 --- a/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift +++ b/CDAKit/HealthKitBridge/CDAKitHealthKitBridge.swift @@ -30,7 +30,7 @@ import Foundation import HealthKit - +import Try /** Provides HealthKit bridging with CDA structures. diff --git a/Podfile b/Podfile index 963a89f..31dfd2d 100644 --- a/Podfile +++ b/Podfile @@ -5,10 +5,12 @@ use_frameworks! target 'CDAKit' do pod 'GRMustache.swift', '~> 2.0.0' pod 'Fuzi', '~> 1.0.0' + pod 'Try', '~> 2.0.0' end target 'CDAKitTests' do pod 'GRMustache.swift', '~> 2.0.0' pod 'Fuzi', '~> 1.0.0' + pod 'Try', '~> 2.0.0' end From 31f272f58f937c8fe6ee33d73e96ffd8cc54a87d Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Sun, 30 Oct 2016 19:49:56 -0400 Subject: [PATCH 13/15] Updating CDAKit.podspec to include Try 2.0.0 (forgot to add that back) and remove the local inclusion of Try --- CDAKit.podspec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CDAKit.podspec b/CDAKit.podspec index ef0dcff..2300c60 100755 --- a/CDAKit.podspec +++ b/CDAKit.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = "8.0" s.requires_arc = true - s.source_files = 'CDAKit/**/*.swift', 'CDAKit/**/WBTry.{h,m}' + s.source_files = 'CDAKit/**/*.swift' s.resource_bundles = { 'CDAKit' => [ 'CDAKit/**/*.mustache', @@ -33,4 +33,5 @@ Pod::Spec.new do |s| s.frameworks = 'HealthKit' s.dependency 'GRMustache.swift', '~> 2.0.0' s.dependency 'Fuzi', '~> 1.0.0' + s.dependency 'Try', '~> 2.0.0' end From f1596541868c1614fb31702f40fe39cbf21e9069 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Mon, 31 Oct 2016 09:45:06 -0400 Subject: [PATCH 14/15] Remove intermediate files from repo --- .../lib/models/record1.swift | 15 --------- .../lib/models/record2.swift | 10 ------ .../lib/models/record3.swift | 10 ------ .../health-data-standards/lib/util/trap.swift | 31 ------------------- 4 files changed, 66 deletions(-) delete mode 100644 CDAKit/health-data-standards/lib/models/record1.swift delete mode 100644 CDAKit/health-data-standards/lib/models/record2.swift delete mode 100644 CDAKit/health-data-standards/lib/models/record3.swift delete mode 100644 CDAKit/health-data-standards/lib/util/trap.swift diff --git a/CDAKit/health-data-standards/lib/models/record1.swift b/CDAKit/health-data-standards/lib/models/record1.swift deleted file mode 100644 index b7ac162..0000000 --- a/CDAKit/health-data-standards/lib/models/record1.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// record1.swift -// CDAKit -// -// Created by Jim on 10/25/16. -// Copyright © 2016 Eric Whitley. All rights reserved. -// - -import Foundation -import Mustache - - - - - diff --git a/CDAKit/health-data-standards/lib/models/record2.swift b/CDAKit/health-data-standards/lib/models/record2.swift deleted file mode 100644 index 29c683e..0000000 --- a/CDAKit/health-data-standards/lib/models/record2.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// record2.swift -// CDAKit -// -// Created by Jim on 10/25/16. -// Copyright © 2016 Eric Whitley. All rights reserved. -// - -import Foundation - diff --git a/CDAKit/health-data-standards/lib/models/record3.swift b/CDAKit/health-data-standards/lib/models/record3.swift deleted file mode 100644 index 50de7d7..0000000 --- a/CDAKit/health-data-standards/lib/models/record3.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// record3.swift -// CDAKit -// -// Created by Jim on 10/25/16. -// Copyright © 2016 Eric Whitley. All rights reserved. -// - -import Foundation - diff --git a/CDAKit/health-data-standards/lib/util/trap.swift b/CDAKit/health-data-standards/lib/util/trap.swift deleted file mode 100644 index e114442..0000000 --- a/CDAKit/health-data-standards/lib/util/trap.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// trap.swift -// Try -// -// Created by Jacob Berkman on 2015-10-19. -// - -import Foundation - -public let tryErrorDomain = "Try" -public let tryExceptionErrorCode = 1 -public let tryExceptionErrorKey = "exception" - -/** - Wraps a closure in a `WBTry.tryBlock` to catch Objective-C exceptions using the Swift error handling model. - - - parameter block: The block of code to run within a `WBTry.tryBlock`. - - throws: Throws an `NSError` if the wrapped code throws an exception. -*/ -public func trap(_ block: @escaping () -> Void) throws { - var exception: Any? - - WBTry.try(block, catchAndRethrow: { - exception = $0 - return false - }, finallyBlock: nil) - - if let e = exception { - throw NSError(domain: tryErrorDomain, code: tryExceptionErrorCode, userInfo: [tryExceptionErrorKey: e]) - } -} From c266ab63789e3253d3bc2d2749c1496bbe2d2187 Mon Sep 17 00:00:00 2001 From: Jim Gerace Date: Mon, 31 Oct 2016 09:56:06 -0400 Subject: [PATCH 15/15] More intermediate file cleanup --- CDAKit/health-data-standards/lib/util/WBTry.h | 27 ------------------ CDAKit/health-data-standards/lib/util/WBTry.m | 28 ------------------- 2 files changed, 55 deletions(-) delete mode 100644 CDAKit/health-data-standards/lib/util/WBTry.h delete mode 100644 CDAKit/health-data-standards/lib/util/WBTry.m diff --git a/CDAKit/health-data-standards/lib/util/WBTry.h b/CDAKit/health-data-standards/lib/util/WBTry.h deleted file mode 100644 index 05e40d9..0000000 --- a/CDAKit/health-data-standards/lib/util/WBTry.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// WBTry.h -// Try -// -// Created by Jacob Berkman on 2014-08-20. -// - -#import - -@interface WBTry : NSObject - -/** - @brief Performs a block of code wrapped in Objective-C exception handling blocks. - @discussion This method accepts a block of code which is performed inside a \@try block. - If the code throws an Objective-C exception, it is caught in a \@catch. If - a catchAndRethrowBlock is provided it is executed, and if it returns YES, the - exception will be rethrown with \@throw. Lastly, if a finallyBlock is provided - we will perform it in within a \@finally block. - @param tryBlock The block to perform within a \@try block. - @param catchAndRethrowBlock An optional block that can be executed if an exception was thrown. - If it returns YES, we rethrow the exception. - @param finallyBlock An optional block that is called in the \@finally block. - - */ -+ (void)tryBlock:(nonnull void (^)(void))tryBlock catchAndRethrowBlock:(nullable BOOL (^)(_Nonnull id))catchAndRethrowBlock finallyBlock:(nullable void (^)(void))finallyBlock; - -@end diff --git a/CDAKit/health-data-standards/lib/util/WBTry.m b/CDAKit/health-data-standards/lib/util/WBTry.m deleted file mode 100644 index 8238f0c..0000000 --- a/CDAKit/health-data-standards/lib/util/WBTry.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// WBTry.m -// Try -// -// Created by Jacob Berkman on 2014-08-20. -// - -#import "WBTry.h" - -@implementation WBTry - -+ (void)tryBlock:(nonnull void (^)(void))tryBlock catchAndRethrowBlock:(nullable BOOL (^)(_Nonnull id))catchAndRethrowBlock finallyBlock:(nullable void (^)(void))finallyBlock { - @try { - tryBlock(); - } - @catch (id exception) { - if (catchAndRethrowBlock && catchAndRethrowBlock(exception)) { - @throw; - } - } - @finally { - if (finallyBlock) { - finallyBlock(); - } - } -} - -@end