import { Versions } from './fhir' ; import { ParsedStructure } from "./model/parsed-structure" ; import { ParsedValueSet } from "./model/parsed-value-set" ; import { ParsedProperty } from "./model/parsed-property" ; import { ParsedSystem } from "./model/parsed-system" ; import { ParsedConcept } from "./model/parsed-concept" ; import { Constants } from "./constants" ; import { ElementDefinition } from "./model/element-definition" ; export class ParseConformance { public parsedStructureDefinitions : { [ key ] : ParsedStructure ; } ; public parsedValueSets : { [ key ] : ParsedValueSet ; } ; public structureDefinitions : any [ ] = [ ] ; private readonly version : string ; private codeSystems : any [ ] ; param { boolean } loadCached param { string } version constructor constructor ( loadCached ? , version ? ) { this . parsedStructureDefinitions = loadCached ? require ( './profiles/types.json' ) : { } ; this . parsedValueSets = loadCached ? require ( './profiles/valuesets.json' ) : { } ; this . version = version || Versions . R4 ; this . codeSystems = [ ] ; this . ensurePropertyMetaData ( ) ; } isBaseProfile ( url ) { let urls ; switch ( this . version ) { case Versions . STU3 : urls = [ 'http://hl7.org/fhir/StructureDefinition/Account' , 'http://hl7.org/fhir/StructureDefinition/ActivityDefinition' , 'http://hl7.org/fhir/StructureDefinition/AllergyIntolerance' , 'http://hl7.org/fhir/StructureDefinition/AdverseEvent' , 'http://hl7.org/fhir/StructureDefinition/Appointment' , 'http://hl7.org/fhir/StructureDefinition/AppointmentResponse' , 'http://hl7.org/fhir/StructureDefinition/AuditEvent' , 'http://hl7.org/fhir/StructureDefinition/Basic' , 'http://hl7.org/fhir/StructureDefinition/Binary' , 'http://hl7.org/fhir/StructureDefinition/BodySite' , 'http://hl7.org/fhir/StructureDefinition/Bundle' , 'http://hl7.org/fhir/StructureDefinition/CapabilityStatement' , 'http://hl7.org/fhir/StructureDefinition/CarePlan' , 'http://hl7.org/fhir/StructureDefinition/CareTeam' , 'http://hl7.org/fhir/StructureDefinition/ChargeItem' , 'http://hl7.org/fhir/StructureDefinition/Claim' , 'http://hl7.org/fhir/StructureDefinition/ClaimResponse' , 'http://hl7.org/fhir/StructureDefinition/ClinicalImpression' , 'http://hl7.org/fhir/StructureDefinition/CodeSystem' , 'http://hl7.org/fhir/StructureDefinition/Communication' , 'http://hl7.org/fhir/StructureDefinition/CommunicationRequest' , 'http://hl7.org/fhir/StructureDefinition/CompartmentDefinition' , 'http://hl7.org/fhir/StructureDefinition/Composition' , 'http://hl7.org/fhir/StructureDefinition/ConceptMap' , 'http://hl7.org/fhir/StructureDefinition/Condition (aka Problem)' , 'http://hl7.org/fhir/StructureDefinition/Consent' , 'http://hl7.org/fhir/StructureDefinition/Contract' , 'http://hl7.org/fhir/StructureDefinition/Coverage' , 'http://hl7.org/fhir/StructureDefinition/DataElement' , 'http://hl7.org/fhir/StructureDefinition/DetectedIssue' , 'http://hl7.org/fhir/StructureDefinition/Device' , 'http://hl7.org/fhir/StructureDefinition/DeviceComponent' , 'http://hl7.org/fhir/StructureDefinition/DeviceMetric' , 'http://hl7.org/fhir/StructureDefinition/DeviceRequest' , 'http://hl7.org/fhir/StructureDefinition/DeviceUseStatement' , 'http://hl7.org/fhir/StructureDefinition/DiagnosticReport' , 'http://hl7.org/fhir/StructureDefinition/DocumentManifest' , 'http://hl7.org/fhir/StructureDefinition/DocumentReference' , 'http://hl7.org/fhir/StructureDefinition/EligibilityRequest' , 'http://hl7.org/fhir/StructureDefinition/EligibilityResponse' , 'http://hl7.org/fhir/StructureDefinition/Encounter' , 'http://hl7.org/fhir/StructureDefinition/Endpoint' , 'http://hl7.org/fhir/StructureDefinition/EnrollmentRequest' , 'http://hl7.org/fhir/StructureDefinition/EnrollmentResponse' , 'http://hl7.org/fhir/StructureDefinition/EpisodeOfCare' , 'http://hl7.org/fhir/StructureDefinition/ExpansionProfile' , 'http://hl7.org/fhir/StructureDefinition/ExplanationOfBenefit' , 'http://hl7.org/fhir/StructureDefinition/FamilyMemberHistory' , 'http://hl7.org/fhir/StructureDefinition/Flag' , 'http://hl7.org/fhir/StructureDefinition/Goal' , 'http://hl7.org/fhir/StructureDefinition/GraphDefinition' , 'http://hl7.org/fhir/StructureDefinition/Group' , 'http://hl7.org/fhir/StructureDefinition/GuidanceResponse' , 'http://hl7.org/fhir/StructureDefinition/HealthcareService' , 'http://hl7.org/fhir/StructureDefinition/ImagingManifest' , 'http://hl7.org/fhir/StructureDefinition/ImagingStudy' , 'http://hl7.org/fhir/StructureDefinition/Immunization' , 'http://hl7.org/fhir/StructureDefinition/ImmunizationRecommendation' , 'http://hl7.org/fhir/StructureDefinition/ImplementationGuide' , 'http://hl7.org/fhir/StructureDefinition/Library' , 'http://hl7.org/fhir/StructureDefinition/Linkage' , 'http://hl7.org/fhir/StructureDefinition/List' , 'http://hl7.org/fhir/StructureDefinition/Location' , 'http://hl7.org/fhir/StructureDefinition/Measure' , 'http://hl7.org/fhir/StructureDefinition/MeasureReport' , 'http://hl7.org/fhir/StructureDefinition/Media' , 'http://hl7.org/fhir/StructureDefinition/Medication' , 'http://hl7.org/fhir/StructureDefinition/MedicationAdministration' , 'http://hl7.org/fhir/StructureDefinition/MedicationDispense' , 'http://hl7.org/fhir/StructureDefinition/MedicationRequest' , 'http://hl7.org/fhir/StructureDefinition/MedicationStatement' , 'http://hl7.org/fhir/StructureDefinition/MessageDefinition' , 'http://hl7.org/fhir/StructureDefinition/MessageHeader' , 'http://hl7.org/fhir/StructureDefinition/NamingSystem' , 'http://hl7.org/fhir/StructureDefinition/NutritionOrder' , 'http://hl7.org/fhir/StructureDefinition/Observation' , 'http://hl7.org/fhir/StructureDefinition/OperationDefinition' , 'http://hl7.org/fhir/StructureDefinition/OperationOutcome' , 'http://hl7.org/fhir/StructureDefinition/Organization' , 'http://hl7.org/fhir/StructureDefinition/Parameters' , 'http://hl7.org/fhir/StructureDefinition/Patient' , 'http://hl7.org/fhir/StructureDefinition/PaymentNotice' , 'http://hl7.org/fhir/StructureDefinition/PaymentReconciliation' , 'http://hl7.org/fhir/StructureDefinition/Person' , 'http://hl7.org/fhir/StructureDefinition/PlanDefinition' , 'http://hl7.org/fhir/StructureDefinition/Practitioner' , 'http://hl7.org/fhir/StructureDefinition/PractitionerRole' , 'http://hl7.org/fhir/StructureDefinition/Procedure' , 'http://hl7.org/fhir/StructureDefinition/ProcedureRequest' , 'http://hl7.org/fhir/StructureDefinition/ProcessRequest' , 'http://hl7.org/fhir/StructureDefinition/ProcessResponse' , 'http://hl7.org/fhir/StructureDefinition/Provenance' , 'http://hl7.org/fhir/StructureDefinition/Questionnaire' , 'http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse' , 'http://hl7.org/fhir/StructureDefinition/ReferralRequest' , 'http://hl7.org/fhir/StructureDefinition/RelatedPerson' , 'http://hl7.org/fhir/StructureDefinition/RequestGroup' , 'http://hl7.org/fhir/StructureDefinition/ResearchStudy' , 'http://hl7.org/fhir/StructureDefinition/ResearchSubject' , 'http://hl7.org/fhir/StructureDefinition/RiskAssessment' , 'http://hl7.org/fhir/StructureDefinition/Schedule' , 'http://hl7.org/fhir/StructureDefinition/SearchParameter' , 'http://hl7.org/fhir/StructureDefinition/Sequence' , 'http://hl7.org/fhir/StructureDefinition/ServiceDefinition' , 'http://hl7.org/fhir/StructureDefinition/Slot' , 'http://hl7.org/fhir/StructureDefinition/Specimen' , 'http://hl7.org/fhir/StructureDefinition/StructureDefinition' , 'http://hl7.org/fhir/StructureDefinition/StructureMap' , 'http://hl7.org/fhir/StructureDefinition/Subscription' , 'http://hl7.org/fhir/StructureDefinition/Substance' , 'http://hl7.org/fhir/StructureDefinition/SupplyDelivery' , 'http://hl7.org/fhir/StructureDefinition/SupplyRequest' , 'http://hl7.org/fhir/StructureDefinition/Task' , 'http://hl7.org/fhir/StructureDefinition/TestScript' , 'http://hl7.org/fhir/StructureDefinition/TestReport' , 'http://hl7.org/fhir/StructureDefinition/ValueSet' , 'http://hl7.org/fhir/StructureDefinition/VisionPrescription' ] ; break ; case Versions . R4 : urls = [ 'http://hl7.org/fhir/StructureDefinition/Account' , 'http://hl7.org/fhir/StructureDefinition/ActivityDefinition' , 'http://hl7.org/fhir/StructureDefinition/AdverseEvent' , 'http://hl7.org/fhir/StructureDefinition/AllergyIntolerance' , 'http://hl7.org/fhir/StructureDefinition/Appointment' , 'http://hl7.org/fhir/StructureDefinition/AppointmentResponse' , 'http://hl7.org/fhir/StructureDefinition/AuditEvent' , 'http://hl7.org/fhir/StructureDefinition/Basic' , 'http://hl7.org/fhir/StructureDefinition/Binary' , 'http://hl7.org/fhir/StructureDefinition/BiologicallyDerivedProduct' , 'http://hl7.org/fhir/StructureDefinition/BodyStructure' , 'http://hl7.org/fhir/StructureDefinition/Bundle' , 'http://hl7.org/fhir/StructureDefinition/CapabilityStatement' , 'http://hl7.org/fhir/StructureDefinition/CarePlan' , 'http://hl7.org/fhir/StructureDefinition/CareTeam' , 'http://hl7.org/fhir/StructureDefinition/CatalogEntry' , 'http://hl7.org/fhir/StructureDefinition/ChargeItem' , 'http://hl7.org/fhir/StructureDefinition/ChargeItemDefinition' , 'http://hl7.org/fhir/StructureDefinition/Claim' , 'http://hl7.org/fhir/StructureDefinition/ClaimResponse' , 'http://hl7.org/fhir/StructureDefinition/ClinicalImpression' , 'http://hl7.org/fhir/StructureDefinition/CodeSystem' , 'http://hl7.org/fhir/StructureDefinition/Communication' , 'http://hl7.org/fhir/StructureDefinition/CommunicationRequest' , 'http://hl7.org/fhir/StructureDefinition/CompartmentDefinition' , 'http://hl7.org/fhir/StructureDefinition/Composition' , 'http://hl7.org/fhir/StructureDefinition/ConceptMap' , 'http://hl7.org/fhir/StructureDefinition/Condition (aka Problem)' , 'http://hl7.org/fhir/StructureDefinition/Consent' , 'http://hl7.org/fhir/StructureDefinition/Contract' , 'http://hl7.org/fhir/StructureDefinition/Coverage' , 'http://hl7.org/fhir/StructureDefinition/CoverageEligibilityRequest' , 'http://hl7.org/fhir/StructureDefinition/CoverageEligibilityResponse' , 'http://hl7.org/fhir/StructureDefinition/DetectedIssue' , 'http://hl7.org/fhir/StructureDefinition/Device' , 'http://hl7.org/fhir/StructureDefinition/DeviceDefinition' , 'http://hl7.org/fhir/StructureDefinition/DeviceMetric' , 'http://hl7.org/fhir/StructureDefinition/DeviceRequest' , 'http://hl7.org/fhir/StructureDefinition/DeviceUseStatement' , 'http://hl7.org/fhir/StructureDefinition/DiagnosticReport' , 'http://hl7.org/fhir/StructureDefinition/DocumentManifest' , 'http://hl7.org/fhir/StructureDefinition/DocumentReference' , 'http://hl7.org/fhir/StructureDefinition/EffectEvidenceSynthesis' , 'http://hl7.org/fhir/StructureDefinition/Encounter' , 'http://hl7.org/fhir/StructureDefinition/Endpoint' , 'http://hl7.org/fhir/StructureDefinition/EnrollmentRequest' , 'http://hl7.org/fhir/StructureDefinition/EnrollmentResponse' , 'http://hl7.org/fhir/StructureDefinition/EpisodeOfCare' , 'http://hl7.org/fhir/StructureDefinition/EventDefinition' , 'http://hl7.org/fhir/StructureDefinition/Evidence' , 'http://hl7.org/fhir/StructureDefinition/EvidenceVariable' , 'http://hl7.org/fhir/StructureDefinition/ExampleScenario' , 'http://hl7.org/fhir/StructureDefinition/ExplanationOfBenefit' , 'http://hl7.org/fhir/StructureDefinition/FamilyMemberHistory' , 'http://hl7.org/fhir/StructureDefinition/Flag' , 'http://hl7.org/fhir/StructureDefinition/Goal' , 'http://hl7.org/fhir/StructureDefinition/GraphDefinition' , 'http://hl7.org/fhir/StructureDefinition/Group' , 'http://hl7.org/fhir/StructureDefinition/GuidanceResponse' , 'http://hl7.org/fhir/StructureDefinition/HealthcareService' , 'http://hl7.org/fhir/StructureDefinition/ImagingStudy' , 'http://hl7.org/fhir/StructureDefinition/Immunization' , 'http://hl7.org/fhir/StructureDefinition/ImmunizationEvaluation' , 'http://hl7.org/fhir/StructureDefinition/ImmunizationRecommendation' , 'http://hl7.org/fhir/StructureDefinition/ImplementationGuide' , 'http://hl7.org/fhir/StructureDefinition/InsurancePlan' , 'http://hl7.org/fhir/StructureDefinition/Invoice' , 'http://hl7.org/fhir/StructureDefinition/Library' , 'http://hl7.org/fhir/StructureDefinition/Linkage' , 'http://hl7.org/fhir/StructureDefinition/List' , 'http://hl7.org/fhir/StructureDefinition/Location' , 'http://hl7.org/fhir/StructureDefinition/Measure' , 'http://hl7.org/fhir/StructureDefinition/MeasureReport' , 'http://hl7.org/fhir/StructureDefinition/Media' , 'http://hl7.org/fhir/StructureDefinition/Medication' , 'http://hl7.org/fhir/StructureDefinition/MedicationAdministration' , 'http://hl7.org/fhir/StructureDefinition/MedicationDispense' , 'http://hl7.org/fhir/StructureDefinition/MedicationKnowledge' , 'http://hl7.org/fhir/StructureDefinition/MedicationRequest' , 'http://hl7.org/fhir/StructureDefinition/MedicationStatement' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProduct' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProductAuthorization' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProductContraindication' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProductIndication' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProductIngredient' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProductInteraction' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProductManufactured' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProductPackaged' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProductPharmaceutical' , 'http://hl7.org/fhir/StructureDefinition/MedicinalProductUndesirableEffect' , 'http://hl7.org/fhir/StructureDefinition/MessageDefinition' , 'http://hl7.org/fhir/StructureDefinition/MessageHeader' , 'http://hl7.org/fhir/StructureDefinition/MolecularSequence' , 'http://hl7.org/fhir/StructureDefinition/amingSystem' , 'http://hl7.org/fhir/StructureDefinition/utritionOrder' , 'http://hl7.org/fhir/StructureDefinition/Observation' , 'http://hl7.org/fhir/StructureDefinition/ObservationDefinition' , 'http://hl7.org/fhir/StructureDefinition/OperationDefinition' , 'http://hl7.org/fhir/StructureDefinition/OperationOutcome' , 'http://hl7.org/fhir/StructureDefinition/Organization' , 'http://hl7.org/fhir/StructureDefinition/OrganizationAffiliation' , 'http://hl7.org/fhir/StructureDefinition/Parameters' , 'http://hl7.org/fhir/StructureDefinition/Patient' , 'http://hl7.org/fhir/StructureDefinition/PaymentNotice' , 'http://hl7.org/fhir/StructureDefinition/PaymentReconciliation' , 'http://hl7.org/fhir/StructureDefinition/Person' , 'http://hl7.org/fhir/StructureDefinition/PlanDefinition' , 'http://hl7.org/fhir/StructureDefinition/Practitioner' , 'http://hl7.org/fhir/StructureDefinition/PractitionerRole' , 'http://hl7.org/fhir/StructureDefinition/Procedure' , 'http://hl7.org/fhir/StructureDefinition/Provenance' , 'http://hl7.org/fhir/StructureDefinition/Questionnaire' , 'http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse' , 'http://hl7.org/fhir/StructureDefinition/RelatedPerson' , 'http://hl7.org/fhir/StructureDefinition/RequestGroup' , 'http://hl7.org/fhir/StructureDefinition/ResearchDefinition' , 'http://hl7.org/fhir/StructureDefinition/ResearchElementDefinition' , 'http://hl7.org/fhir/StructureDefinition/ResearchStudy' , 'http://hl7.org/fhir/StructureDefinition/ResearchSubject' , 'http://hl7.org/fhir/StructureDefinition/RiskAssessment' , 'http://hl7.org/fhir/StructureDefinition/RiskEvidenceSynthesis' , 'http://hl7.org/fhir/StructureDefinition/Schedule' , 'http://hl7.org/fhir/StructureDefinition/SearchParameter' , 'http://hl7.org/fhir/StructureDefinition/ServiceRequest' , 'http://hl7.org/fhir/StructureDefinition/Slot' , 'http://hl7.org/fhir/StructureDefinition/Specimen' , 'http://hl7.org/fhir/StructureDefinition/SpecimenDefinition' , 'http://hl7.org/fhir/StructureDefinition/StructureDefinition' , 'http://hl7.org/fhir/StructureDefinition/StructureMap' , 'http://hl7.org/fhir/StructureDefinition/Subscription' , 'http://hl7.org/fhir/StructureDefinition/Substance' , 'http://hl7.org/fhir/StructureDefinition/SubstancePolymer' , 'http://hl7.org/fhir/StructureDefinition/SubstanceReferenceInformation' , 'http://hl7.org/fhir/StructureDefinition/SubstanceSpecification' , 'http://hl7.org/fhir/StructureDefinition/SupplyDelivery' , 'http://hl7.org/fhir/StructureDefinition/SupplyRequest' , 'http://hl7.org/fhir/StructureDefinition/Task' , 'http://hl7.org/fhir/StructureDefinition/TerminologyCapabilities' , 'http://hl7.org/fhir/StructureDefinition/TestReport' , 'http://hl7.org/fhir/StructureDefinition/TestScript' , 'http://hl7.org/fhir/StructureDefinition/ValueSet' , 'http://hl7.org/fhir/StructureDefinition/VerificationResult' , 'http://hl7.org/fhir/StructureDefinition/VisionPrescription' ] ; break ; } return urls . indexOf ( url ) >= 0 ; } private ensurePropertyMetaData ( properties ? ) { if ( properties ) { const primitiveProperties = properties . filter ( p => Constants . PrimitiveTypes . indexOf ( p . _type ) >= 0 ) . filter ( p => ! p . _name . startsWith ( '_' ) ) ; for ( let primitiveProp of primitiveProperties ) { const primitivePropIndex = properties . indexOf ( primitiveProp ) ; let foundMeta = properties . find ( p => p . _name === "_" + primitiveProp . _name ) ; if ( ! foundMeta ) { foundMeta = { _name : "_" + primitiveProp . _name , _type : "Element" , _multiple : primitiveProp . _multiple } ; properties . splice ( primitivePropIndex + 1 , 0 , foundMeta ) ; } this . ensurePropertyMetaData ( primitiveProp . _properties || [ ] ) ; } const backboneProperties = properties . filter ( p => p . _type === 'BackboneElement' ) ; for ( let backboneProp of backboneProperties ) { this . ensurePropertyMetaData ( backboneProp . _properties || [ ] ) ; } } else { for ( const profileId in this . parsedStructureDefinitions ) { const parsedProfile = this . parsedStructureDefinitions [ profileId ] ; this . ensurePropertyMetaData ( parsedProfile . _properties ) ; } } } param valueSets { ParsedValueSet [ ] } return { ParsedValueSet [ ] } private sortValueSetDependencies ( valueSets ) { const ret = [ ] ; function addValueSet ( valueSetUrl ) { const foundValueSet = valueSets . find ( nextValueSet => nextValueSet . url === valueSetUrl ) ; if ( ! foundValueSet ) { return ; } if ( foundValueSet . compose ) { ( foundValueSet . compose . include || [ ] ) . forEach ( include => { addValueSet ( include . valueSet ) ; } ) ; } if ( ret . indexOf ( foundValueSet ) < 0 ) { ret . push ( foundValueSet ) ; } } valueSets . forEach ( valueSet => { addValueSet ( valueSet . url ) ; } ) ; return ret ; } public loadCodeSystem ( codeSystem ) { if ( ! codeSystem ) { return ; } const foundCodeSystem = this . codeSystems . find ( nextCodeSystem => { return nextCodeSystem . url === codeSystem . url || nextCodeSystem . id === codeSystem . id ; } ) ; if ( ! foundCodeSystem ) { this . codeSystems . push ( codeSystem ) ; } } ; param { Bundle } bundle public parseBundle ( bundle ) { if ( ! bundle || ! bundle . entry ) { return ; } bundle . entry . filter ( entry => { return entry . resource . resourceType === 'CodeSystem' ; } ) . forEach ( entry => { this . loadCodeSystem ( entry . resource ) ; } ) ; let valueSets = bundle . entry . filter ( entry => { return entry . resource . resourceType === 'ValueSet' ; } ) . map ( entry => { return entry . resource ; } ) ; valueSets = this . sortValueSetDependencies ( valueSets ) ; valueSets . forEach ( valueSet => { this . parseValueSet ( valueSet ) ; } ) ; bundle . entry . filter ( entry => { if ( entry . resource . resourceType !== 'StructureDefinition' ) { return false ; } const resource = entry . resource ; return ! ( resource . kind != 'resource' && resource . kind != 'complex-type' && resource . kind != 'primitive-type' ) ; } ) . forEach ( entry => { this . parseStructureDefinition ( entry . resource ) ; } ) ; } param { StructureDefinition } structureDefinition returns { ParsedStructure } public parseStructureDefinition ( structureDefinition ) { const uid = ( "0000" + ( ( Math . random ( ) * Math . pow ( 36 , 4 ) ) | 0 ) . toString ( 36 ) ) . slice ( - 4 ) ; const parsedStructureDefinition = { _url : structureDefinition . url , _type : 'Resource' , _kind : structureDefinition . kind , _properties : [ ] } ; this . parsedStructureDefinitions [ structureDefinition . id || uid ] = parsedStructureDefinition ; const loadedStructureDefinition = this . structureDefinitions . find ( sd => sd . url === structureDefinition . url ) ; if ( ! loadedStructureDefinition ) { this . structureDefinitions . push ( structureDefinition ) ; } if ( structureDefinition . snapshot && structureDefinition . snapshot . element ) { for ( let x in structureDefinition . snapshot . element ) { const element = structureDefinition . snapshot . element [ x ] as ElementDefinition ; let elementId = structureDefinition . snapshot . element [ x ] . id ; elementId = elementId . substring ( structureDefinition . type . length + 1 ) ; if ( ! element . max ) { throw 'Expected all base resource elements to have a max value' ; } if ( ! elementId || elementId . indexOf ( '.' ) > 0 || ! element . type ) { continue ; } if ( element . type . length === 1 && element . type [ 0 ] . code !== 'Reference' && ! elementId . includes ( '[x]' ) && ! elementId . includes ( ':' ) ) { let type = elementId === 'id' ? 'id' : element . type [ 0 ] . code || 'string' ; if ( type . startsWith ( 'http://hl7.org/fhirpath/System.' ) ) { type = type . substring ( 'http://hl7.org/fhirpath/System.' . length ) ; type = type . charAt ( 0 ) . toLowerCase ( ) + type . substring ( 1 ) ; } const newProperty = { _name : elementId , _type : type , _multiple : ParseConformance . isMultipleAllowed ( element ) , _required : element . min === 1 } ; parsedStructureDefinition . _properties . push ( newProperty ) ; this . populateValueSet ( element , newProperty ) ; if ( element . type [ 0 ] . code == 'BackboneElement' || element . type [ 0 ] . code == 'Element' ) { newProperty . _properties = [ ] ; this . populateBackboneElement ( parsedStructureDefinition , element . id , structureDefinition ) ; } } else if ( elementId . endsWith ( '[x]' ) ) { elementId = elementId . substring ( 0 , elementId . length - 3 ) ; const elementPrevPath = element . id . substring ( 0 , element . id . lastIndexOf ( '.' ) ) ; const elementRequired = structureDefinition . snapshot . element . filter ( ( e ) => { const choiceRequired = e . id . startsWith ( elementPrevPath + '.' + elementId ) && e . id !== elementPrevPath + '.' + elementId + '[x]' && e . id . split ( '.' ) . length === element . id . split ( '.' ) . length && e . min >= 1 ; const sliceRequired = e . id . startsWith ( elementPrevPath + '.' + elementId + '[x]:' ) && e . id . split ( '.' ) . length === element . id . split ( '.' ) . length && e . min >= 1 ; return choiceRequired || sliceRequired ; } ) . length > 0 ; for ( let y in element . type ) { let choiceType = element . type [ y ] . code ; choiceType = choiceType . substring ( 0 , 1 ) . toUpperCase ( ) + choiceType . substring ( 1 ) ; const choiceElementId = elementId + choiceType ; const newProperty = { _name : choiceElementId , _choice : elementId , _type : element . type [ y ] . code , _multiple : ParseConformance . isMultipleAllowed ( element ) , _required : element . min === 1 || elementRequired } ; this . populateValueSet ( element , newProperty ) ; parsedStructureDefinition . _properties . push ( newProperty ) ; } } else if ( ! elementId . includes ( ':' ) ) { let isReference = true ; for ( let y in element . type ) { if ( element . type [ y ] . code !== 'Reference' ) { isReference = false ; break ; } } let targetProfiles = null ; if ( element . type . length > 0 ) { targetProfiles = element . type [ 0 ] . targetProfile ; } if ( isReference ) { parsedStructureDefinition . _properties . push ( { _name : elementId , _type : 'Reference' , _targetProfiles : targetProfiles , _multiple : ParseConformance . isMultipleAllowed ( element ) , _required : element . min === 1 } ) ; } else { console . log ( elementId ) ; } } } } this . ensurePropertyMetaData ( parsedStructureDefinition . _properties ) ; return parsedStructureDefinition ; } param { ValueSet } valueSet returns { ParsedValueSet } public parseValueSet ( valueSet ) { const newValueSet = { systems : [ ] } ; if ( valueSet . expansion && valueSet . expansion . contains ) { for ( let i = 0 ; i < valueSet . expansion . contains . length ; i ++ ) { const contains = valueSet . expansion . contains [ i ] ; if ( contains . inactive || contains . abstract ) { continue ; } let foundSystem = newValueSet . systems . find ( system => { return system . uri === contains . system ; } ) ; if ( ! foundSystem ) { foundSystem = { uri : contains . system , codes : [ ] } ; newValueSet . systems . push ( foundSystem ) ; } foundSystem . codes . push ( { code : contains . code , display : contains . display } ) ; } } else if ( valueSet . compose ) { for ( let i = 0 ; i < valueSet . compose . include . length ; i ++ ) { const include = valueSet . compose . include [ i ] ; if ( include . system ) { let foundSystem = newValueSet . systems . find ( system => { return system . uri === include . system ; } ) ; if ( ! foundSystem ) { foundSystem = { uri : include . system , codes : [ ] } ; newValueSet . systems . push ( foundSystem ) ; } const foundCodeSystem = this . codeSystems . find ( codeSystem => { return codeSystem . url === include . system ; } ) ; if ( foundCodeSystem ) { const addConcept = ( concept ) => { foundSystem . codes . push ( { code : concept . code , display : concept . display } ) ; ( concept . concept || [ ] ) . forEach ( next => addConcept ( next ) ) ; } ; ( foundCodeSystem . concept || [ ] ) . forEach ( concept => addConcept ( concept ) ) ; } } if ( include . valueSet ) { const includeValueSet = this . parsedValueSets [ include . valueSet ] ; if ( includeValueSet ) { includeValueSet . systems . forEach ( includeSystem => { const foundSystem = newValueSet . systems . find ( nextSystem => { return nextSystem . uri === includeSystem . uri ; } ) ; if ( ! foundSystem ) { newValueSet . systems . push ( { uri : includeSystem . uri , codes : [ ] . concat ( < ParsedConcept [ ] > includeSystem . codes ) } ) ; } else { foundSystem . codes = foundSystem . codes . concat ( includeSystem . codes ) ; } } ) ; } } if ( include . concept ) { const systemUri = include . system || '' ; let foundSystem = newValueSet . systems . find ( nextSystem => { return nextSystem . uri === systemUri ; } ) ; if ( ! foundSystem ) { foundSystem = { uri : systemUri , codes : [ ] } ; newValueSet . systems . push ( foundSystem ) ; } const codes = include . concept . map ( concept => { return { code : concept . code , display : concept . display } ; } ) ; foundSystem . codes = foundSystem . codes . concat ( codes ) ; } } } const systemsWithCodes = newValueSet . systems . filter ( system => { return system . codes && system . codes . length > 0 ; } ) ; if ( systemsWithCodes . length > 0 ) { this . parsedValueSets [ valueSet . url ] = newValueSet ; return newValueSet ; } } param { ElementDefinition } element param { ParsedProperty } property private public populateValueSet ( element , property ) { if ( element . binding ) { const binding = element . binding ; if ( binding . strength ) { property . _valueSetStrength = binding . strength ; } if ( this . version === Versions . R4 && binding . valueSet ) { property . _valueSet = binding . valueSet ; } else if ( this . version === Versions . STU3 && binding . valueSetReference && binding . valueSetReference . reference ) { property . _valueSet = binding . valueSetReference . reference ; } } } param { ParsedStructureDefinition } parsedStructureDefinition param { string } parentElementId param { StructureDefinition } structureDefinition private public populateBackboneElement ( parsedStructureDefinition , parentElementId , structureDefinition ) { for ( let y in structureDefinition . snapshot . element ) { const backboneElement = structureDefinition . snapshot . element [ y ] ; let backboneElementId = backboneElement . id ; if ( ! backboneElementId . startsWith ( parentElementId + '.' ) || backboneElementId . split ( '.' ) . length !== parentElementId . split ( '.' ) . length + 1 ) { continue ; } backboneElementId = backboneElementId . substring ( structureDefinition . type . length + 1 ) ; const parentElementIdSplit = parentElementId . substring ( structureDefinition . type . length + 1 ) . split ( '.' ) ; let parentBackboneElement = null ; for ( let j = 0 ; j < parentElementIdSplit . length ; j ++ ) { const properties = ! parentBackboneElement ? parsedStructureDefinition . _properties : parentBackboneElement . _properties ; parentBackboneElement = properties . find ( property => property . _name == parentElementIdSplit [ j ] ) ; if ( ! parentBackboneElement ) { throw 'Parent backbone element not found' ; } } if ( parentBackboneElement ) { if ( ! backboneElement . type ) { let type = 'string' ; if ( backboneElement . contentReference ) { type = backboneElement . contentReference ; } parentBackboneElement . _properties . push ( { _name : backboneElementId . substring ( backboneElementId . lastIndexOf ( '.' ) + 1 ) , _type : type , _multiple : ParseConformance . isMultipleAllowed ( backboneElement ) , _required : backboneElement . min === 1 } ) ; } else if ( backboneElement . type . length == 1 && ! backboneElementId . includes ( '[x]' ) && ! backboneElementId . includes ( ':' ) ) { let type = backboneElement . type [ 0 ] . code ; if ( type . startsWith ( 'http://hl7.org/fhirpath/System.' ) ) { type = type . substring ( 'http://hl7.org/fhirpath/System.' . length ) ; type = type . charAt ( 0 ) . toLowerCase ( ) + type . substring ( 1 ) ; } const newProperty = { _name : backboneElementId . substring ( backboneElementId . lastIndexOf ( '.' ) + 1 ) , _type : type , _multiple : ParseConformance . isMultipleAllowed ( backboneElement ) , _required : backboneElement . min === 1 , _properties : [ ] } ; parentBackboneElement . _properties . push ( newProperty ) ; this . populateValueSet ( backboneElement , newProperty ) ; if ( backboneElement . type [ 0 ] . code === 'BackboneElement' || backboneElement . type [ 0 ] . code == 'Element' ) { this . populateBackboneElement ( parsedStructureDefinition , structureDefinition . snapshot . element [ y ] . id , structureDefinition ) ; } } else if ( backboneElement . id . endsWith ( '[x]' ) ) { const anySliceRequired = structureDefinition . snapshot . element . filter ( ( e ) => { return backboneElement . id . split ( '.' ) . length === e . id . split ( '.' ) . length && e . id . includes ( backboneElement ) && e . min >= 1 ; } ) . length > 0 ; for ( let y in backboneElement . type ) { let choiceType = backboneElement . type [ y ] . code ; choiceType = choiceType . substring ( 0 , 1 ) . toUpperCase ( ) + choiceType . substring ( 1 ) ; const choiceElementId = backboneElement . id . substring ( backboneElement . id . lastIndexOf ( '.' ) + 1 , backboneElement . id . length - 3 ) + choiceType ; const newProperty = { _name : choiceElementId , _choice : backboneElement . id . substring ( backboneElement . id . lastIndexOf ( '.' ) + 1 ) , _type : backboneElement . type [ y ] . code , _multiple : ParseConformance . isMultipleAllowed ( backboneElement ) , _required : backboneElement . min === 1 || anySliceRequired } ; parentBackboneElement . _properties . push ( newProperty ) ; this . populateValueSet ( backboneElement , newProperty ) ; } } else if ( ! backboneElementId . includes ( ':' ) ) { let isReference = true ; for ( let z in backboneElement . type ) { if ( backboneElement . type [ z ] . code !== 'Reference' ) { isReference = false ; break ; } } if ( ! isReference ) { throw 'Did not find a reference... not sure what to do' ; } let newProperty = { _name : backboneElementId . substring ( backboneElementId . lastIndexOf ( '.' ) + 1 ) , _type : 'Reference' , _multiple : ParseConformance . isMultipleAllowed ( backboneElement ) , _required : backboneElement . min === 1 } ; parentBackboneElement . _properties . push ( newProperty ) ; this . populateValueSet ( backboneElement , newProperty ) ; } } else { throw 'Unexpected backbone parent element id' ; } } } private static isMultipleAllowed ( element ) { if ( element . base && element . base . hasOwnProperty ( 'max' ) ) { return element . base . max !== '0' && element . base . max !== '1' ; } return element . max !== '0' && element . max !== '1' ; } }