From 6a6c71e1affde91a2b140a398dd4dd64ecfc95e7 Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Wed, 9 Aug 2023 11:43:11 +0800 Subject: [PATCH 01/15] Implement source generation --- .../Education.StructureDefinition.json | 89 + .../Patient.StructureDefinition.json | 3286 +++++++++++++++++ SampleSourceGen/SampleSourceGen.csproj | 26 + .../Education.StructureDefinition.json | 89 + .../Patient.StructureDefinition.json | 3286 +++++++++++++++++ TestSourceGen/Program.cs | 26 + TestSourceGen/TestSourceGen.csproj | 27 + fhir-codegen.sln | 18 + .../FhirNameConventionExtensions.cs | 12 +- ...Microsoft.Health.Fhir.CodeGenCommon.csproj | 18 +- .../Models/FhirComplex.cs | 2 +- .../Models/FhirOperation.cs | 2 +- .../Models/FhirUtils.cs | 9 +- .../Shim.cs | 45 + .../FhirSourceGenerator.cs | 136 + ...crosoft.Health.Fhir.SourceGenerator.csproj | 70 + .../Language/CSharp2.cs | 6 + .../Language/CSharpBasic.cs | 6 + .../Language/CSharpFirely2.cs | 52 +- .../Language/CSharpFirely2IG.cs | 7 + .../Language/Cytoscape.cs | 7 + .../Language/ILanguage.cs | 6 + .../Language/Info.cs | 7 + .../Language/LangOpenApiV1.cs | 6 + .../Language/LanguageSupportFiles.cs | 3 + .../Language/OpenApi/LangOpenApi.cs | 6 + .../Language/OpenApi/ModelBuilder.cs | 4 + .../Language/TypeScript.cs | 6 + .../Language/TypeScript2.cs | 6 + .../Language/TypeScriptSdk/TypeScriptSdk.cs | 14 +- .../Manager/FhirManager.cs | 2 +- .../Microsoft.Health.Fhir.SpecManager.csproj | 16 +- .../PackageManager/FhirCacheService.cs | 4 +- src/Microsoft.Health.Fhir.SpecManager/Shim.cs | 200 + src/fhirCsR2/Shim.cs | 13 + src/fhirCsR2/fhirCsR2.csproj | 18 +- 36 files changed, 7490 insertions(+), 40 deletions(-) create mode 100644 SampleSourceGen/Education.StructureDefinition.json create mode 100644 SampleSourceGen/Patient.StructureDefinition.json create mode 100644 SampleSourceGen/SampleSourceGen.csproj create mode 100644 TestSourceGen/Education.StructureDefinition.json create mode 100644 TestSourceGen/Patient.StructureDefinition.json create mode 100644 TestSourceGen/Program.cs create mode 100644 TestSourceGen/TestSourceGen.csproj create mode 100644 src/Microsoft.Health.Fhir.CodeGenCommon/Shim.cs create mode 100644 src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs create mode 100644 src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj create mode 100644 src/Microsoft.Health.Fhir.SpecManager/Shim.cs create mode 100644 src/fhirCsR2/Shim.cs diff --git a/SampleSourceGen/Education.StructureDefinition.json b/SampleSourceGen/Education.StructureDefinition.json new file mode 100644 index 000000000..be9469fcd --- /dev/null +++ b/SampleSourceGen/Education.StructureDefinition.json @@ -0,0 +1,89 @@ +{ + "resourceType": "StructureDefinition", + "id": "Education", + "url": "http://hl7.org/fhir/StructureDefinition/Education", + "version": "0.1", + "name": "Education", + "status": "draft", + "publisher": "Firely", + "description": "Study or other form of education that a person has done.", + "copyright": "Copyright (C) 2019 Firely", + "fhirVersion": "4.0.1", + "kind": "resource", + "abstract": false, + "type": "Education", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", + "derivation": "specialization", + "snapshot": { + "element": [ + { + "id": "Education.subject", + "path": "Education.subject", + "short": "Who was educated?", + "definition": "Person who has done this education.", + "min": 1, + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": "http://hl7.org/fhir/StructureDefinition/Person" + }, + { + "code": "Reference", + "targetProfile": "http://hl7.org/fhir/StructureDefinition/Patient" + }, + { + "code": "Reference", + "targetProfile": "http://hl7.org/fhir/StructureDefinition/Practitioner" + } + ] + }, + { + "id": "Education.institute", + "path": "Education.institute", + "short": "Where did you do this study?", + "definition": "Educational institute, like a university or training company", + "min": 0, + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": "http://hl7.org/fhir/StructureDefinition/Organization" + } + ] + }, + { + "id": "Education.study", + "path": "Education.study", + "short": "What study?", + "definition": "Name of the study that the subject followed.", + "min": 1, + "max": "1", + "type": [ + { + "code": "string", + "profile": "http://hl7.org/fhir/StructureDefinition/string" + } + ] + }, + { + "id": "Education.graduated[x]", + "path": "Education.graduated[x]", + "short": "Did subject graduate for the study?", + "definition": "Did the subject graduate for the study? If possible enter the date of graduation.", + "min": 1, + "max": "1", + "type": [ + { + "code": "boolean", + "profile": "http://hl7.org/fhir/StructureDefinition/boolean" + }, + { + "code": "date", + "profile": "http://hl7.org/fhir/StructureDefinition/date" + } + ] + } + ] + } +} diff --git a/SampleSourceGen/Patient.StructureDefinition.json b/SampleSourceGen/Patient.StructureDefinition.json new file mode 100644 index 000000000..55585265f --- /dev/null +++ b/SampleSourceGen/Patient.StructureDefinition.json @@ -0,0 +1,3286 @@ +{ + "resourceType": "StructureDefinition", + "id": "Patient", + "meta": { + "lastUpdated": "2022-05-28T12:47:40.239+10:00" + }, + "text": { + "status": "generated", + "div": "
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
NameFlagsCard.TypeDescription & Constraints\"doco\"
\".\"\".\" Patient NDomainResourceInformation about an individual or animal receiving health care services
Elements defined in Ancestors: id, meta, implicitRules, language, text, contained, extension, modifierExtension
\".\"\".\"\".\" identifier Σ0..*IdentifierAn identifier for this patient
\".\"\".\"\".\" active ?!Σ0..1booleanWhether this patient's record is in active use
\".\"\".\"\".\" name Σ0..*HumanNameA name associated with the patient
\".\"\".\"\".\" telecom Σ0..*ContactPointA contact detail for the individual
\".\"\".\"\".\" gender Σ0..1codemale | female | other | unknown
AdministrativeGender (Required)
\".\"\".\"\".\" birthDate Σ0..1dateThe date of birth for the individual
\".\"\".\"\".\" deceased[x] ?!Σ0..1Indicates if the individual is deceased or not
\".\"\".\"\".\"\".\" deceasedBooleanboolean
\".\"\".\"\".\"\".\" deceasedDateTimedateTime
\".\"\".\"\".\" address Σ0..*AddressAn address for the individual
\".\"\".\"\".\" maritalStatus 0..1CodeableConceptMarital (civil) status of a patient
MaritalStatus (Extensible)
\".\"\".\"\".\" multipleBirth[x] 0..1Whether patient is part of a multiple birth
\".\"\".\"\".\"\".\" multipleBirthBooleanboolean
\".\"\".\"\".\"\".\" multipleBirthIntegerinteger
\".\"\".\"\".\" photo 0..*AttachmentImage of the patient
\".\"\".\"\".\" contact I0..*BackboneElementA contact party (e.g. guardian, partner, friend) for the patient
+ Rule: SHALL at least contain a contact's details or a reference to an organization
\".\"\".\"\".\"\".\" relationship 0..*CodeableConceptThe kind of relationship
Patient Contact Relationship (Extensible)
\".\"\".\"\".\"\".\" name 0..1HumanNameA name associated with the contact person
\".\"\".\"\".\"\".\" telecom 0..*ContactPointA contact detail for the person
\".\"\".\"\".\"\".\" address 0..1AddressAddress for the contact person
\".\"\".\"\".\"\".\" gender 0..1codemale | female | other | unknown
AdministrativeGender (Required)
\".\"\".\"\".\"\".\" organization I0..1Reference(Organization)Organization that is associated with the contact
\".\"\".\"\".\"\".\" period 0..1PeriodThe period during which this contact person or organization is valid to be contacted relating to this patient
\".\"\".\"\".\" communication 0..*BackboneElementA language which may be used to communicate with the patient about his or her health
\".\"\".\"\".\"\".\" language 1..1CodeableConceptThe language which can be used to communicate with the patient about his or her health
Common Languages (Preferred but limited to AllLanguages)
\".\"\".\"\".\"\".\" preferred 0..1booleanLanguage preference indicator
\".\"\".\"\".\" generalPractitioner 0..*Reference(Organization | Practitioner | PractitionerRole)Patient's nominated primary care provider
\".\"\".\"\".\" managingOrganization Σ0..1Reference(Organization)Organization that is the custodian of the patient record
\".\"\".\"\".\" link ?!Σ0..*BackboneElementLink to another patient resource that concerns the same actual person
\".\"\".\"\".\"\".\" other Σ1..1Reference(Patient | RelatedPerson)The other patient or related person resource that the link refers to
\".\"\".\"\".\"\".\" type Σ1..1codereplaced-by | replaces | refer | seealso
LinkType (Required)

\"doco\" Documentation for this format
" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-category", + "valueString": "Base.Individuals" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm", + "valueInteger": 5 + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-security-category", + "valueCode": "patient" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg", + "valueCode": "pa" + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/Patient", + "version": "4.3.0", + "name": "Patient", + "status": "active", + "experimental": false, + "date": "2022-05-28T12:47:40+10:00", + "publisher": "Health Level Seven International (Patient Administration)", + "contact": [ + { + "telecom": [ + { + "system": "url", + "value": "http://hl7.org/fhir" + } + ] + }, + { + "telecom": [ + { + "system": "url", + "value": "http://www.hl7.org/Special/committees/pafm/index.cfm" + } + ] + } + ], + "description": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", + "purpose": "Tracking patient is the center of the healthcare process.", + "fhirVersion": "4.3.0", + "mapping": [ + { + "identity": "rim", + "uri": "http://hl7.org/v3", + "name": "RIM Mapping" + }, + { + "identity": "cda", + "uri": "http://hl7.org/v3/cda", + "name": "CDA (R2)" + }, + { + "identity": "w5", + "uri": "http://hl7.org/fhir/fivews", + "name": "FiveWs Pattern Mapping" + }, + { + "identity": "v2", + "uri": "http://hl7.org/v2", + "name": "HL7 v2 Mapping" + }, + { + "identity": "loinc", + "uri": "http://loinc.org", + "name": "LOINC code for the element" + } + ], + "kind": "resource", + "abstract": false, + "type": "Patient", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", + "derivation": "specialization", + "snapshot": { + "element": [ + { + "id": "Patient", + "path": "Patient", + "short": "Information about an individual or animal receiving health care services", + "definition": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", + "alias": [ "SubjectOfCare Client Resident" ], + "min": 0, + "max": "*", + "base": { + "path": "Patient", + "min": 0, + "max": "*" + }, + "constraint": [ + { + "key": "dom-2", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL NOT contain nested Resources", + "expression": "contained.contained.empty()", + "xpath": "not(parent::f:contained and f:contained)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-3", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource", + "expression": "contained.where(((id.exists() and ('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url)))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(uri) = '#').exists()).not()).trace('unmatched', id).empty()", + "xpath": "not(exists(for $contained in f:contained return $contained[not(exists(parent::*/descendant::f:reference/@value=concat('#', $contained/*/f:id/@value)) or exists(descendant::f:reference[@value='#']))]))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-4", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated", + "expression": "contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:versionId)) and not(exists(f:contained/*/f:meta/f:lastUpdated))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-5", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a security label", + "expression": "contained.meta.security.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:security))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice", + "valueBoolean": true + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation", + "valueMarkdown": "When a resource has no narrative, only systems that fully understand the data can display the resource to a human safely. Including a human readable representation in the resource makes for a much more robust eco-system and cheaper handling of resources by intermediary systems. Some ecosystems restrict distribution of resources to only those systems that do fully understand the resources, and as a consequence implementers may believe that the narrative is superfluous. However experience shows that such eco-systems often open up to new participants over time." + } + ], + "key": "dom-6", + "severity": "warning", + "human": "A resource should have narrative for robust management", + "expression": "text.`div`.exists()", + "xpath": "exists(f:text/h:div)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Entity. Role, or Act" + }, + { + "identity": "rim", + "map": "Patient[classCode=PAT]" + }, + { + "identity": "cda", + "map": "ClinicalDocument.recordTarget.patientRole" + }, + { + "identity": "w5", + "map": "administrative.individual" + } + ] + }, + { + "id": "Patient.id", + "path": "Patient.id", + "short": "Logical id of this artifact", + "definition": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "comment": "The only time that a resource does not have an id is when it is being submitted to the server using a create operation.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "id" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true + }, + { + "id": "Patient.meta", + "path": "Patient.meta", + "short": "Metadata about the resource", + "definition": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.meta", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Meta" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true + }, + { + "id": "Patient.implicitRules", + "path": "Patient.implicitRules", + "short": "A set of rules under which this content was created", + "definition": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "comment": "Asserting this rule set restricts the content to be only understood by a limited set of trading partners. This inherently limits the usefulness of the data in the long term. However, the existing health eco-system is highly fractured, and not yet ready to define, collect, and exchange data in a generally computable sense. Wherever possible, implementers and/or specification writers should avoid using this element. Often, when used, the URL is a reference to an implementation guide that defines these special rules as part of it's narrative along with other profiles, value sets, etc.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.implicitRules", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "uri" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because the implicit rules may provide additional knowledge about the resource that modifies it's meaning or interpretation", + "isSummary": true + }, + { + "id": "Patient.language", + "path": "Patient.language", + "short": "Language of the resource content", + "definition": "The base language in which the resource is written.", + "comment": "Language is provided to support indexing and accessibility (typically, services such as text to speech use the language tag). The html language tag in the narrative applies to the narrative. The language tag on the resource may be used to specify the language of other presentations generated from the data in the resource. Not all the content has to be in the base language. The Resource.language should not be assumed to apply to the narrative automatically. If a language is specified, it should it also be specified on the div element in the html (see rules in HTML5 for information about the relationship between xml:lang and the html lang attribute).", + "min": 0, + "max": "1", + "base": { + "path": "Resource.language", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + } + }, + { + "id": "Patient.text", + "path": "Patient.text", + "short": "Text summary of the resource, for human interpretation", + "definition": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "comment": "Contained resources do not have narrative. Resources that are not contained SHOULD have a narrative. In some cases, a resource may only have text with little or no additional discrete data (as long as all minOccurs=1 elements are satisfied). This may be necessary for data from legacy systems where information is captured as a \"text blob\" or where text is additionally entered raw or narrated and encoded information is added later.", + "alias": [ + "narrative", + "html", + "xhtml", + "display" + ], + "min": 0, + "max": "1", + "base": { + "path": "DomainResource.text", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Narrative" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Act.text?" + } + ] + }, + { + "id": "Patient.contained", + "path": "Patient.contained", + "short": "Contained, inline Resources", + "definition": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, and nor can they have their own independent transaction scope.", + "comment": "This should never be done when the content can be identified properly, as once identification is lost, it is extremely difficult (and context dependent) to restore it again. Contained resources may have profiles and tags In their meta elements, but SHALL NOT have security labels.", + "alias": [ + "inline resources", + "anonymous resources", + "contained resources" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.contained", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Resource" + } + ], + "constraint": [ + { + "key": "dom-r4b", + "severity": "warning", + "human": "Containing new R4B resources within R4 resources may cause interoperability issues if instances are shared with R4 systems", + "expression": "($this is Citation or $this is Evidence or $this is EvidenceReport or $this is EvidenceVariable or $this is MedicinalProductDefinition or $this is PackagedProductDefinition or $this is AdministrableProductDefinition or $this is Ingredient or $this is ClinicalUseDefinition or $this is RegulatedAuthorization or $this is SubstanceDefinition or $this is SubscriptionStatus or $this is SubscriptionTopic) implies (%resource is Citation or %resource is Evidence or %resource is EvidenceReport or %resource is EvidenceVariable or %resource is MedicinalProductDefinition or %resource is PackagedProductDefinition or %resource is AdministrableProductDefinition or %resource is Ingredient or %resource is ClinicalUseDefinition or %resource is RegulatedAuthorization or %resource is SubstanceDefinition or %resource is SubscriptionStatus or %resource is SubscriptionTopic)", + "xpath": "not(f:Citation|f:Evidence|f:EvidenceReport|f:EvidenceVariable|f:MedicinalProductDefinition|f:PackagedProductDefinition|f:AdministrableProductDefinition|f:Ingredient|f:ClinicalUseDefinition|f:RegulatedAuthorization|f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic) or not(parent::f:Citation|parent::f:Evidence|parent::f:EvidenceReport|parent::f:EvidenceVariable|parent::f:MedicinalProductDefinition|parent::f:PackagedProductDefinition|parent::f:AdministrableProductDefinition|parent::f:Ingredient|parent::f:ClinicalUseDefinition|parent::f:RegulatedAuthorization|parent::f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic)", + "source": "http://hl7.org/fhir/StructureDefinition/Patient" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.extension", + "path": "Patient.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.modifierExtension", + "path": "Patient.modifierExtension", + "short": "Extensions that cannot be ignored", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the resource that contains them", + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.identifier", + "path": "Patient.identifier", + "short": "An identifier for this patient", + "definition": "An identifier for this patient.", + "requirements": "Patients are almost always assigned specific numerical identifiers.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.identifier", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Identifier" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.identifier" + }, + { + "identity": "v2", + "map": "PID-3" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": ".id" + } + ] + }, + { + "id": "Patient.active", + "path": "Patient.active", + "short": "Whether this patient's record is in active use", + "definition": "Whether this patient record is in active use. \nMany systems use this property to mark as non-current patients, such as those that have not been seen for a period of time based on an organization's business rules.\n\nIt is often used to filter patient lists to exclude inactive patients\n\nDeceased patients may also be marked as inactive for the same reasons, but may be active for some time after death.", + "comment": "If a record is inactive, and linked to an active record, then future patient/record updates should occur on the other patient.", + "requirements": "Need to be able to mark a patient record as not to be used because it was created in error.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.active", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "boolean" + } + ], + "meaningWhenMissing": "This resource is generally assumed to be active if no value is provided for the active element", + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labelled as a modifier because it is a status element that can indicate that a record should not be treated as valid", + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.status" + }, + { + "identity": "rim", + "map": "statusCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.name", + "path": "Patient.name", + "short": "A name associated with the patient", + "definition": "A name associated with the individual.", + "comment": "A patient may have multiple names with different uses or applicable periods. For animals, the name is a \"HumanName\" in the sense that is assigned and used by humans and has the same patterns.", + "requirements": "Need to be able to track the patient by multiple names. Examples are your official name and a partner name.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.name", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "HumanName" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-5, PID-9" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": ".patient.name" + } + ] + }, + { + "id": "Patient.telecom", + "path": "Patient.telecom", + "short": "A contact detail for the individual", + "definition": "A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted.", + "comment": "A Patient may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently and also to help with identification. The address might not go directly to the individual, but may reach another party that is able to proxy for the patient (i.e. home phone, or pet owner's phone).", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.telecom", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "ContactPoint" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-13, PID-14, PID-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": ".telecom" + } + ] + }, + { + "id": "Patient.gender", + "path": "Patient.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes.", + "comment": "The gender might not match the biological sex as determined by genetics or the individual's preferred identification. Note that for both humans and particularly animals, there are other legitimate possibilities than male and female, though the vast majority of systems and contexts only support male and female. Systems providing decision support or enforcing business rules should ideally do this on the basis of Observations dealing with the specific sex or gender aspect of interest (anatomical, chromosomal, social, etc.) However, because these observations are infrequently recorded, defaulting to the administrative gender is common practice. Where such defaulting occurs, rule enforcement should allow for the variation between administrative and biological, chromosomal and other gender aspects. For example, an alert about a hysterectomy on a male should be handled as a warning or overridable error, not a \"hard\" error. See the Patient Gender and Sex section for additional information about communicating patient gender and sex.", + "requirements": "Needed for identification of the individual, in combination with (at least) name and birth date.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.gender", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-8" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": ".patient.administrativeGenderCode" + } + ] + }, + { + "id": "Patient.birthDate", + "path": "Patient.birthDate", + "short": "The date of birth for the individual", + "definition": "The date of birth for the individual.", + "comment": "At least an estimated year should be provided as a guess if the real DOB is unknown There is a standard extension \"patient-birthTime\" available that should be used where Time is required (such as in maternity/infant care systems).", + "requirements": "Age of the individual drives many clinical processes.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.birthDate", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "date" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-7" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/birthTime" + }, + { + "identity": "cda", + "map": ".patient.birthTime" + }, + { + "identity": "loinc", + "map": "21112-8" + } + ] + }, + { + "id": "Patient.deceased[x]", + "path": "Patient.deceased[x]", + "short": "Indicates if the individual is deceased or not", + "definition": "Indicates if the individual is deceased or not.", + "comment": "If there's no value in the instance, it means there is no statement on whether or not the individual is deceased. Most systems will interpret the absence of a value as a sign of the person being alive.", + "requirements": "The fact that a patient is deceased influences the clinical process. Also, in human communication and relation management it is necessary to know whether the person is alive.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.deceased[x]", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "boolean" + }, + { + "code": "dateTime" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because once a patient is marked as deceased, the actions that are appropriate to perform on the patient may be significantly different.", + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-30 (bool) and PID-29 (datetime)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.address", + "path": "Patient.address", + "short": "An address for the individual", + "definition": "An address for the individual.", + "comment": "Patient may have multiple addresses with different uses or applicable periods.", + "requirements": "May need to keep track of patient addresses for contacting, billing or reporting requirements and also to help with identification.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.address", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Address" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-11" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": ".addr" + } + ] + }, + { + "id": "Patient.maritalStatus", + "path": "Patient.maritalStatus", + "short": "Marital (civil) status of a patient", + "definition": "This field contains a patient's most recent marital (civil) status.", + "requirements": "Most, if not all systems capture it.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.maritalStatus", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "MaritalStatus" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "extensible", + "description": "The domestic partnership status of a person.", + "valueSet": "http://hl7.org/fhir/ValueSet/marital-status" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-16" + }, + { + "identity": "rim", + "map": "player[classCode=PSN]/maritalStatusCode" + }, + { + "identity": "cda", + "map": ".patient.maritalStatusCode" + } + ] + }, + { + "id": "Patient.multipleBirth[x]", + "path": "Patient.multipleBirth[x]", + "short": "Whether patient is part of a multiple birth", + "definition": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", + "comment": "Where the valueInteger is provided, the number is the birth number in the sequence. E.g. The middle birth in triplets would be valueInteger=2 and the third born would have valueInteger=3 If a boolean value was provided for this triplets example, then all 3 patient records would have valueBoolean=true (the ordering is not indicated).", + "requirements": "For disambiguation of multiple-birth children, especially relevant where the care provider doesn't meet the patient, such as labs.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.multipleBirth[x]", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "boolean" + }, + { + "code": "integer" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-24 (bool), PID-25 (integer)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthOrderNumber" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.photo", + "path": "Patient.photo", + "short": "Image of the patient", + "definition": "Image of the patient.", + "comment": "Guidelines:\n* Use id photos, not clinical photos.\n* Limit dimensions to thumbnail.\n* Keep byte count low to ease resource updates.", + "requirements": "Many EHR systems have the capability to capture an image of the patient. Fits with newer social media usage too.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.photo", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Attachment" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "OBX-5 - needs a profile" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/desc" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name", + "valueString": "Contact" + } + ], + "path": "Patient.contact", + "short": "A contact party (e.g. guardian, partner, friend) for the patient", + "definition": "A contact party (e.g. guardian, partner, friend) for the patient.", + "comment": "Contact covers all kinds of contact parties: family members, business contacts, guardians, caregivers. Not applicable to register pedigree and family ties beyond use of having contact.", + "requirements": "Need to track people you can contact about the patient.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.contact", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "pat-1", + "severity": "error", + "human": "SHALL at least contain a contact's details or a reference to an organization", + "expression": "name.exists() or telecom.exists() or address.exists() or organization.exists()", + "xpath": "exists(f:name) or exists(f:telecom) or exists(f:address) or exists(f:organization)", + "source": "http://hl7.org/fhir/StructureDefinition/Patient" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/scopedRole[classCode=CON]" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.id", + "path": "Patient.contact.id", + "representation": [ "xmlAttr" ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "string" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.extension", + "path": "Patient.contact.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.modifierExtension", + "path": "Patient.contact.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.contact.relationship", + "path": "Patient.contact.relationship", + "short": "The kind of relationship", + "definition": "The nature of the relationship between the patient and the contact person.", + "requirements": "Used to determine which contact person is the most relevant to approach, depending on circumstances.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.contact.relationship", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "ContactRelationship" + } + ], + "strength": "extensible", + "description": "The nature of the relationship between a patient and a contact person for that patient.", + "valueSet": "http://hl7.org/fhir/ValueSet/patient-contactrelationship" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-7, NK1-3" + }, + { + "identity": "rim", + "map": "code" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.name", + "path": "Patient.contact.name", + "short": "A name associated with the contact person", + "definition": "A name associated with the contact person.", + "requirements": "Contact persons need to be identified by name, but it is uncommon to need details about multiple other names for that contact person.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.name", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "HumanName" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-2" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.telecom", + "path": "Patient.contact.telecom", + "short": "A contact detail for the person", + "definition": "A contact detail for the person, e.g. a telephone number or an email address.", + "comment": "Contact may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently, and also to help with identification.", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.contact.telecom", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "ContactPoint" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-5, NK1-6, NK1-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.address", + "path": "Patient.contact.address", + "short": "Address for the contact person", + "definition": "Address for the contact person.", + "requirements": "Need to keep track where the contact person can be contacted per postal mail or visited.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.address", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Address" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-4" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.gender", + "path": "Patient.contact.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the contact person is considered to have for administration and record keeping purposes.", + "requirements": "Needed to address the person correctly.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.gender", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-15" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.organization", + "path": "Patient.contact.organization", + "short": "Organization that is associated with the contact", + "definition": "Organization on behalf of which the contact is acting or for which the contact is working.", + "requirements": "For guardians or business related contacts, the organization is relevant.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.organization", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] + } + ], + "condition": [ "pat-1" ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-13, NK1-30, NK1-31, NK1-32, NK1-41" + }, + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.period", + "path": "Patient.contact.period", + "short": "The period during which this contact person or organization is valid to be contacted relating to this patient", + "definition": "The period during which this contact person or organization is valid to be contacted relating to this patient.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.period", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Period" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "effectiveTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication", + "path": "Patient.communication", + "short": "A language which may be used to communicate with the patient about his or her health", + "definition": "A language which may be used to communicate with the patient about his or her health.", + "comment": "If no language is specified, this *implies* that the default local language is spoken. If you need to convey proficiency for multiple modes, then you need multiple Patient.Communication associations. For animals, language is not a relevant field, and should be absent from the instance. If the Patient does not speak the default local language, then the Interpreter Required Standard can be used to explicitly declare that an interpreter is required.", + "requirements": "If a patient does not speak the local language, interpreters may be required, so languages spoken and proficiency are important things to keep track of both for patient and other persons of interest.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.communication", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "LanguageCommunication" + }, + { + "identity": "cda", + "map": "patient.languageCommunication" + } + ] + }, + { + "id": "Patient.communication.id", + "path": "Patient.communication.id", + "representation": [ "xmlAttr" ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "string" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication.extension", + "path": "Patient.communication.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication.modifierExtension", + "path": "Patient.communication.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.communication.language", + "path": "Patient.communication.language", + "short": "The language which can be used to communicate with the patient about his or her health", + "definition": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-EN\" for England English.", + "comment": "The structure aa-BB with this exact casing is one the most widely used notations for locale. However not all systems actually code this but instead have it as free text. Hence CodeableConcept instead of code as the data type.", + "requirements": "Most systems in multilingual countries will want to convey language. Not all systems actually need the regional dialect.", + "min": 1, + "max": "1", + "base": { + "path": "Patient.communication.language", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-15, LAN-2" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/languageCommunication/code" + }, + { + "identity": "cda", + "map": ".languageCode" + } + ] + }, + { + "id": "Patient.communication.preferred", + "path": "Patient.communication.preferred", + "short": "Language preference indicator", + "definition": "Indicates whether or not the patient prefers this language (over other languages he masters up a certain level).", + "comment": "This language is specifically identified for communicating healthcare information.", + "requirements": "People that master multiple languages up to certain level may prefer one or more, i.e. feel more confident in communicating in a particular language making other languages sort of a fall back method.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.communication.preferred", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "boolean" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-15" + }, + { + "identity": "rim", + "map": "preferenceInd" + }, + { + "identity": "cda", + "map": ".preferenceInd" + } + ] + }, + { + "id": "Patient.generalPractitioner", + "path": "Patient.generalPractitioner", + "short": "Patient's nominated primary care provider", + "definition": "Patient's nominated care provider.", + "comment": "This may be the primary care provider (in a GP context), or it may be a patient nominated care manager in a community/disability setting, or even organization that will provide people to perform the care provider roles. It is not to be used to record Care Teams, these should be in a CareTeam resource that may be linked to the CarePlan or EpisodeOfCare resources.\nMultiple GPs may be recorded against the patient for various reasons, such as a student that has his home GP listed along with the GP at university during the school semesters, or a \"fly-in/fly-out\" worker that has the onsite GP also included with his home GP to remain aware of medical issues.\n\nJurisdictions may decide that they can profile this down to 1 if desired, or 1 per type.", + "alias": [ "careProvider" ], + "min": 0, + "max": "*", + "base": { + "path": "Patient.generalPractitioner", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization", + "http://hl7.org/fhir/StructureDefinition/Practitioner", + "http://hl7.org/fhir/StructureDefinition/PractitionerRole" + ] + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PD1-4" + }, + { + "identity": "rim", + "map": "subjectOf.CareEvent.performer.AssignedEntity" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.managingOrganization", + "path": "Patient.managingOrganization", + "short": "Organization that is the custodian of the patient record", + "definition": "Organization that is the custodian of the patient record.", + "comment": "There is only one managing organization for a specific patient record. Other organizations will have their own Patient record, and may use the Link property to join the records together (or a Person resource which can include confidence ratings for the association).", + "requirements": "Need to know who recognizes this patient record, manages and updates it.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.managingOrganization", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": ".providerOrganization" + } + ] + }, + { + "id": "Patient.link", + "path": "Patient.link", + "short": "Link to another patient resource that concerns the same actual person", + "definition": "Link to another patient resource that concerns the same actual patient.", + "comment": "There is no assumption that linked patient records have mutual links.", + "requirements": "There are multiple use cases: \n\n* Duplicate patient records due to the clerical errors associated with the difficulties of identifying humans consistently, and \n* Distribution of patient information across multiple servers.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.link", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because it might not be the main Patient resource, and the referenced patient should be used instead of this Patient record. This is when the link.type value is 'replaced-by'", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "outboundLink" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.id", + "path": "Patient.link.id", + "representation": [ "xmlAttr" ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "string" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.extension", + "path": "Patient.link.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.modifierExtension", + "path": "Patient.link.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.link.other", + "path": "Patient.link.other", + "short": "The other patient or related person resource that the link refers to", + "definition": "The other patient resource that the link refers to.", + "comment": "Referencing a RelatedPerson here removes the need to use a Person record to associate a Patient and RelatedPerson as the same individual.", + "min": 1, + "max": "1", + "base": { + "path": "Patient.link.other", + "min": 1, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy", + "valueBoolean": false + } + ], + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Patient", + "http://hl7.org/fhir/StructureDefinition/RelatedPerson" + ] + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-3, MRG-1" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.type", + "path": "Patient.link.type", + "short": "replaced-by | replaces | refer | seealso", + "definition": "The type of link between this patient resource and another patient resource.", + "min": 1, + "max": "1", + "base": { + "path": "Patient.link.type", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "LinkType" + } + ], + "strength": "required", + "description": "The type of link between this patient resource and another patient resource.", + "valueSet": "http://hl7.org/fhir/ValueSet/link-type|4.3.0" + }, + "mapping": [ + { + "identity": "rim", + "map": "typeCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + } + ] + }, + "differential": { + "element": [ + { + "id": "Patient", + "path": "Patient", + "short": "Information about an individual or animal receiving health care services", + "definition": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", + "alias": [ "SubjectOfCare Client Resident" ], + "min": 0, + "max": "*", + "mustSupport": false, + "isModifier": false, + "mapping": [ + { + "identity": "rim", + "map": "Patient[classCode=PAT]" + }, + { + "identity": "cda", + "map": "ClinicalDocument.recordTarget.patientRole" + }, + { + "identity": "w5", + "map": "administrative.individual" + } + ] + }, + { + "id": "Patient.identifier", + "path": "Patient.identifier", + "short": "An identifier for this patient", + "definition": "An identifier for this patient.", + "requirements": "Patients are almost always assigned specific numerical identifiers.", + "min": 0, + "max": "*", + "type": [ + { + "code": "Identifier" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.identifier" + }, + { + "identity": "v2", + "map": "PID-3" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": ".id" + } + ] + }, + { + "id": "Patient.active", + "path": "Patient.active", + "short": "Whether this patient's record is in active use", + "definition": "Whether this patient record is in active use. \nMany systems use this property to mark as non-current patients, such as those that have not been seen for a period of time based on an organization's business rules.\n\nIt is often used to filter patient lists to exclude inactive patients\n\nDeceased patients may also be marked as inactive for the same reasons, but may be active for some time after death.", + "comment": "If a record is inactive, and linked to an active record, then future patient/record updates should occur on the other patient.", + "requirements": "Need to be able to mark a patient record as not to be used because it was created in error.", + "min": 0, + "max": "1", + "type": [ + { + "code": "boolean" + } + ], + "meaningWhenMissing": "This resource is generally assumed to be active if no value is provided for the active element", + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labelled as a modifier because it is a status element that can indicate that a record should not be treated as valid", + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.status" + }, + { + "identity": "rim", + "map": "statusCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.name", + "path": "Patient.name", + "short": "A name associated with the patient", + "definition": "A name associated with the individual.", + "comment": "A patient may have multiple names with different uses or applicable periods. For animals, the name is a \"HumanName\" in the sense that is assigned and used by humans and has the same patterns.", + "requirements": "Need to be able to track the patient by multiple names. Examples are your official name and a partner name.", + "min": 0, + "max": "*", + "type": [ + { + "code": "HumanName" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-5, PID-9" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": ".patient.name" + } + ] + }, + { + "id": "Patient.telecom", + "path": "Patient.telecom", + "short": "A contact detail for the individual", + "definition": "A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted.", + "comment": "A Patient may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently and also to help with identification. The address might not go directly to the individual, but may reach another party that is able to proxy for the patient (i.e. home phone, or pet owner's phone).", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "type": [ + { + "code": "ContactPoint" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-13, PID-14, PID-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": ".telecom" + } + ] + }, + { + "id": "Patient.gender", + "path": "Patient.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes.", + "comment": "The gender might not match the biological sex as determined by genetics or the individual's preferred identification. Note that for both humans and particularly animals, there are other legitimate possibilities than male and female, though the vast majority of systems and contexts only support male and female. Systems providing decision support or enforcing business rules should ideally do this on the basis of Observations dealing with the specific sex or gender aspect of interest (anatomical, chromosomal, social, etc.) However, because these observations are infrequently recorded, defaulting to the administrative gender is common practice. Where such defaulting occurs, rule enforcement should allow for the variation between administrative and biological, chromosomal and other gender aspects. For example, an alert about a hysterectomy on a male should be handled as a warning or overridable error, not a \"hard\" error. See the Patient Gender and Sex section for additional information about communicating patient gender and sex.", + "requirements": "Needed for identification of the individual, in combination with (at least) name and birth date.", + "min": 0, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-8" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": ".patient.administrativeGenderCode" + } + ] + }, + { + "id": "Patient.birthDate", + "path": "Patient.birthDate", + "short": "The date of birth for the individual", + "definition": "The date of birth for the individual.", + "comment": "At least an estimated year should be provided as a guess if the real DOB is unknown There is a standard extension \"patient-birthTime\" available that should be used where Time is required (such as in maternity/infant care systems).", + "requirements": "Age of the individual drives many clinical processes.", + "min": 0, + "max": "1", + "type": [ + { + "code": "date" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-7" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/birthTime" + }, + { + "identity": "cda", + "map": ".patient.birthTime" + }, + { + "identity": "loinc", + "map": "21112-8" + } + ] + }, + { + "id": "Patient.deceased[x]", + "path": "Patient.deceased[x]", + "short": "Indicates if the individual is deceased or not", + "definition": "Indicates if the individual is deceased or not.", + "comment": "If there's no value in the instance, it means there is no statement on whether or not the individual is deceased. Most systems will interpret the absence of a value as a sign of the person being alive.", + "requirements": "The fact that a patient is deceased influences the clinical process. Also, in human communication and relation management it is necessary to know whether the person is alive.", + "min": 0, + "max": "1", + "type": [ + { + "code": "boolean" + }, + { + "code": "dateTime" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because once a patient is marked as deceased, the actions that are appropriate to perform on the patient may be significantly different.", + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-30 (bool) and PID-29 (datetime)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.address", + "path": "Patient.address", + "short": "An address for the individual", + "definition": "An address for the individual.", + "comment": "Patient may have multiple addresses with different uses or applicable periods.", + "requirements": "May need to keep track of patient addresses for contacting, billing or reporting requirements and also to help with identification.", + "min": 0, + "max": "*", + "type": [ + { + "code": "Address" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-11" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": ".addr" + } + ] + }, + { + "id": "Patient.maritalStatus", + "path": "Patient.maritalStatus", + "short": "Marital (civil) status of a patient", + "definition": "This field contains a patient's most recent marital (civil) status.", + "requirements": "Most, if not all systems capture it.", + "min": 0, + "max": "1", + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "MaritalStatus" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "extensible", + "description": "The domestic partnership status of a person.", + "valueSet": "http://hl7.org/fhir/ValueSet/marital-status" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-16" + }, + { + "identity": "rim", + "map": "player[classCode=PSN]/maritalStatusCode" + }, + { + "identity": "cda", + "map": ".patient.maritalStatusCode" + } + ] + }, + { + "id": "Patient.multipleBirth[x]", + "path": "Patient.multipleBirth[x]", + "short": "Whether patient is part of a multiple birth", + "definition": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", + "comment": "Where the valueInteger is provided, the number is the birth number in the sequence. E.g. The middle birth in triplets would be valueInteger=2 and the third born would have valueInteger=3 If a boolean value was provided for this triplets example, then all 3 patient records would have valueBoolean=true (the ordering is not indicated).", + "requirements": "For disambiguation of multiple-birth children, especially relevant where the care provider doesn't meet the patient, such as labs.", + "min": 0, + "max": "1", + "type": [ + { + "code": "boolean" + }, + { + "code": "integer" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-24 (bool), PID-25 (integer)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthOrderNumber" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.photo", + "path": "Patient.photo", + "short": "Image of the patient", + "definition": "Image of the patient.", + "comment": "Guidelines:\n* Use id photos, not clinical photos.\n* Limit dimensions to thumbnail.\n* Keep byte count low to ease resource updates.", + "requirements": "Many EHR systems have the capability to capture an image of the patient. Fits with newer social media usage too.", + "min": 0, + "max": "*", + "type": [ + { + "code": "Attachment" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "OBX-5 - needs a profile" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/desc" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name", + "valueString": "Contact" + } + ], + "path": "Patient.contact", + "short": "A contact party (e.g. guardian, partner, friend) for the patient", + "definition": "A contact party (e.g. guardian, partner, friend) for the patient.", + "comment": "Contact covers all kinds of contact parties: family members, business contacts, guardians, caregivers. Not applicable to register pedigree and family ties beyond use of having contact.", + "requirements": "Need to track people you can contact about the patient.", + "min": 0, + "max": "*", + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "pat-1", + "severity": "error", + "human": "SHALL at least contain a contact's details or a reference to an organization", + "expression": "name.exists() or telecom.exists() or address.exists() or organization.exists()", + "xpath": "exists(f:name) or exists(f:telecom) or exists(f:address) or exists(f:organization)", + "source": "http://hl7.org/fhir/StructureDefinition/Patient" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/scopedRole[classCode=CON]" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.relationship", + "path": "Patient.contact.relationship", + "short": "The kind of relationship", + "definition": "The nature of the relationship between the patient and the contact person.", + "requirements": "Used to determine which contact person is the most relevant to approach, depending on circumstances.", + "min": 0, + "max": "*", + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "ContactRelationship" + } + ], + "strength": "extensible", + "description": "The nature of the relationship between a patient and a contact person for that patient.", + "valueSet": "http://hl7.org/fhir/ValueSet/patient-contactrelationship" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-7, NK1-3" + }, + { + "identity": "rim", + "map": "code" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.name", + "path": "Patient.contact.name", + "short": "A name associated with the contact person", + "definition": "A name associated with the contact person.", + "requirements": "Contact persons need to be identified by name, but it is uncommon to need details about multiple other names for that contact person.", + "min": 0, + "max": "1", + "type": [ + { + "code": "HumanName" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-2" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.telecom", + "path": "Patient.contact.telecom", + "short": "A contact detail for the person", + "definition": "A contact detail for the person, e.g. a telephone number or an email address.", + "comment": "Contact may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently, and also to help with identification.", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "type": [ + { + "code": "ContactPoint" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-5, NK1-6, NK1-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.address", + "path": "Patient.contact.address", + "short": "Address for the contact person", + "definition": "Address for the contact person.", + "requirements": "Need to keep track where the contact person can be contacted per postal mail or visited.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Address" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-4" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.gender", + "path": "Patient.contact.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the contact person is considered to have for administration and record keeping purposes.", + "requirements": "Needed to address the person correctly.", + "min": 0, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-15" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.organization", + "path": "Patient.contact.organization", + "short": "Organization that is associated with the contact", + "definition": "Organization on behalf of which the contact is acting or for which the contact is working.", + "requirements": "For guardians or business related contacts, the organization is relevant.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] + } + ], + "condition": [ "pat-1" ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-13, NK1-30, NK1-31, NK1-32, NK1-41" + }, + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.period", + "path": "Patient.contact.period", + "short": "The period during which this contact person or organization is valid to be contacted relating to this patient", + "definition": "The period during which this contact person or organization is valid to be contacted relating to this patient.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Period" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "effectiveTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication", + "path": "Patient.communication", + "short": "A language which may be used to communicate with the patient about his or her health", + "definition": "A language which may be used to communicate with the patient about his or her health.", + "comment": "If no language is specified, this *implies* that the default local language is spoken. If you need to convey proficiency for multiple modes, then you need multiple Patient.Communication associations. For animals, language is not a relevant field, and should be absent from the instance. If the Patient does not speak the default local language, then the Interpreter Required Standard can be used to explicitly declare that an interpreter is required.", + "requirements": "If a patient does not speak the local language, interpreters may be required, so languages spoken and proficiency are important things to keep track of both for patient and other persons of interest.", + "min": 0, + "max": "*", + "type": [ + { + "code": "BackboneElement" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "LanguageCommunication" + }, + { + "identity": "cda", + "map": "patient.languageCommunication" + } + ] + }, + { + "id": "Patient.communication.language", + "path": "Patient.communication.language", + "short": "The language which can be used to communicate with the patient about his or her health", + "definition": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-EN\" for England English.", + "comment": "The structure aa-BB with this exact casing is one the most widely used notations for locale. However not all systems actually code this but instead have it as free text. Hence CodeableConcept instead of code as the data type.", + "requirements": "Most systems in multilingual countries will want to convey language. Not all systems actually need the regional dialect.", + "min": 1, + "max": "1", + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-15, LAN-2" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/languageCommunication/code" + }, + { + "identity": "cda", + "map": ".languageCode" + } + ] + }, + { + "id": "Patient.communication.preferred", + "path": "Patient.communication.preferred", + "short": "Language preference indicator", + "definition": "Indicates whether or not the patient prefers this language (over other languages he masters up a certain level).", + "comment": "This language is specifically identified for communicating healthcare information.", + "requirements": "People that master multiple languages up to certain level may prefer one or more, i.e. feel more confident in communicating in a particular language making other languages sort of a fall back method.", + "min": 0, + "max": "1", + "type": [ + { + "code": "boolean" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-15" + }, + { + "identity": "rim", + "map": "preferenceInd" + }, + { + "identity": "cda", + "map": ".preferenceInd" + } + ] + }, + { + "id": "Patient.generalPractitioner", + "path": "Patient.generalPractitioner", + "short": "Patient's nominated primary care provider", + "definition": "Patient's nominated care provider.", + "comment": "This may be the primary care provider (in a GP context), or it may be a patient nominated care manager in a community/disability setting, or even organization that will provide people to perform the care provider roles. It is not to be used to record Care Teams, these should be in a CareTeam resource that may be linked to the CarePlan or EpisodeOfCare resources.\nMultiple GPs may be recorded against the patient for various reasons, such as a student that has his home GP listed along with the GP at university during the school semesters, or a \"fly-in/fly-out\" worker that has the onsite GP also included with his home GP to remain aware of medical issues.\n\nJurisdictions may decide that they can profile this down to 1 if desired, or 1 per type.", + "alias": [ "careProvider" ], + "min": 0, + "max": "*", + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization", + "http://hl7.org/fhir/StructureDefinition/Practitioner", + "http://hl7.org/fhir/StructureDefinition/PractitionerRole" + ] + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PD1-4" + }, + { + "identity": "rim", + "map": "subjectOf.CareEvent.performer.AssignedEntity" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.managingOrganization", + "path": "Patient.managingOrganization", + "short": "Organization that is the custodian of the patient record", + "definition": "Organization that is the custodian of the patient record.", + "comment": "There is only one managing organization for a specific patient record. Other organizations will have their own Patient record, and may use the Link property to join the records together (or a Person resource which can include confidence ratings for the association).", + "requirements": "Need to know who recognizes this patient record, manages and updates it.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": ".providerOrganization" + } + ] + }, + { + "id": "Patient.link", + "path": "Patient.link", + "short": "Link to another patient resource that concerns the same actual person", + "definition": "Link to another patient resource that concerns the same actual patient.", + "comment": "There is no assumption that linked patient records have mutual links.", + "requirements": "There are multiple use cases: \n\n* Duplicate patient records due to the clerical errors associated with the difficulties of identifying humans consistently, and \n* Distribution of patient information across multiple servers.", + "min": 0, + "max": "*", + "type": [ + { + "code": "BackboneElement" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because it might not be the main Patient resource, and the referenced patient should be used instead of this Patient record. This is when the link.type value is 'replaced-by'", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "outboundLink" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.other", + "path": "Patient.link.other", + "short": "The other patient or related person resource that the link refers to", + "definition": "The other patient resource that the link refers to.", + "comment": "Referencing a RelatedPerson here removes the need to use a Person record to associate a Patient and RelatedPerson as the same individual.", + "min": 1, + "max": "1", + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy", + "valueBoolean": false + } + ], + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Patient", + "http://hl7.org/fhir/StructureDefinition/RelatedPerson" + ] + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-3, MRG-1" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.type", + "path": "Patient.link.type", + "short": "replaced-by | replaces | refer | seealso", + "definition": "The type of link between this patient resource and another patient resource.", + "min": 1, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "LinkType" + } + ], + "strength": "required", + "description": "The type of link between this patient resource and another patient resource.", + "valueSet": "http://hl7.org/fhir/ValueSet/link-type|4.3.0" + }, + "mapping": [ + { + "identity": "rim", + "map": "typeCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + } + ] + } +} diff --git a/SampleSourceGen/SampleSourceGen.csproj b/SampleSourceGen/SampleSourceGen.csproj new file mode 100644 index 000000000..43a7a123a --- /dev/null +++ b/SampleSourceGen/SampleSourceGen.csproj @@ -0,0 +1,26 @@ + + + + net6.0 + true + $(BaseIntermediateOutputPath)\GeneratedFiles + + + + + PreserveNewest + + + + + + + + + + + + + + + diff --git a/TestSourceGen/Education.StructureDefinition.json b/TestSourceGen/Education.StructureDefinition.json new file mode 100644 index 000000000..88f3832a4 --- /dev/null +++ b/TestSourceGen/Education.StructureDefinition.json @@ -0,0 +1,89 @@ +{ + "resourceType": "StructureDefinition", + "id": "Education", + "url": "http://hl7.org/fhir/StructureDefinition/Education", + "version": "0.1", + "name": "Education", + "status": "draft", + "publisher": "Firely", + "description": "Study or other form of education that a person has done.", + "copyright": "Copyright (C) 2019 Firely", + "fhirVersion": "4.0.1", + "kind": "resource", + "abstract": false, + "type": "Education", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", + "derivation": "specialization", + "differential": { + "element": [ + { + "id": "Education.subject", + "path": "Education.subject", + "short": "Who was educated?", + "definition": "Person who has done this education.", + "min": 1, + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": "http://hl7.org/fhir/StructureDefinition/Person" + }, + { + "code": "Reference", + "targetProfile": "http://hl7.org/fhir/StructureDefinition/Patient" + }, + { + "code": "Reference", + "targetProfile": "http://hl7.org/fhir/StructureDefinition/Practitioner" + } + ] + }, + { + "id": "Education.institute", + "path": "Education.institute", + "short": "Where did you do this study?", + "definition": "Educational institute, like a university or training company", + "min": 0, + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": "http://hl7.org/fhir/StructureDefinition/Organization" + } + ] + }, + { + "id": "Education.study", + "path": "Education.study", + "short": "What study?", + "definition": "Name of the study that the subject followed.", + "min": 1, + "max": "1", + "type": [ + { + "code": "string", + "profile": "http://hl7.org/fhir/StructureDefinition/string" + } + ] + }, + { + "id": "Education.graduated[x]", + "path": "Education.graduated[x]", + "short": "Did subject graduate for the study?", + "definition": "Did the subject graduate for the study? If possible enter the date of graduation.", + "min": 1, + "max": "1", + "type": [ + { + "code": "boolean", + "profile": "http://hl7.org/fhir/StructureDefinition/boolean" + }, + { + "code": "date", + "profile": "http://hl7.org/fhir/StructureDefinition/date" + } + ] + } + ] + } +} diff --git a/TestSourceGen/Patient.StructureDefinition.json b/TestSourceGen/Patient.StructureDefinition.json new file mode 100644 index 000000000..55585265f --- /dev/null +++ b/TestSourceGen/Patient.StructureDefinition.json @@ -0,0 +1,3286 @@ +{ + "resourceType": "StructureDefinition", + "id": "Patient", + "meta": { + "lastUpdated": "2022-05-28T12:47:40.239+10:00" + }, + "text": { + "status": "generated", + "div": "
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
NameFlagsCard.TypeDescription & Constraints\"doco\"
\".\"\".\" Patient NDomainResourceInformation about an individual or animal receiving health care services
Elements defined in Ancestors: id, meta, implicitRules, language, text, contained, extension, modifierExtension
\".\"\".\"\".\" identifier Σ0..*IdentifierAn identifier for this patient
\".\"\".\"\".\" active ?!Σ0..1booleanWhether this patient's record is in active use
\".\"\".\"\".\" name Σ0..*HumanNameA name associated with the patient
\".\"\".\"\".\" telecom Σ0..*ContactPointA contact detail for the individual
\".\"\".\"\".\" gender Σ0..1codemale | female | other | unknown
AdministrativeGender (Required)
\".\"\".\"\".\" birthDate Σ0..1dateThe date of birth for the individual
\".\"\".\"\".\" deceased[x] ?!Σ0..1Indicates if the individual is deceased or not
\".\"\".\"\".\"\".\" deceasedBooleanboolean
\".\"\".\"\".\"\".\" deceasedDateTimedateTime
\".\"\".\"\".\" address Σ0..*AddressAn address for the individual
\".\"\".\"\".\" maritalStatus 0..1CodeableConceptMarital (civil) status of a patient
MaritalStatus (Extensible)
\".\"\".\"\".\" multipleBirth[x] 0..1Whether patient is part of a multiple birth
\".\"\".\"\".\"\".\" multipleBirthBooleanboolean
\".\"\".\"\".\"\".\" multipleBirthIntegerinteger
\".\"\".\"\".\" photo 0..*AttachmentImage of the patient
\".\"\".\"\".\" contact I0..*BackboneElementA contact party (e.g. guardian, partner, friend) for the patient
+ Rule: SHALL at least contain a contact's details or a reference to an organization
\".\"\".\"\".\"\".\" relationship 0..*CodeableConceptThe kind of relationship
Patient Contact Relationship (Extensible)
\".\"\".\"\".\"\".\" name 0..1HumanNameA name associated with the contact person
\".\"\".\"\".\"\".\" telecom 0..*ContactPointA contact detail for the person
\".\"\".\"\".\"\".\" address 0..1AddressAddress for the contact person
\".\"\".\"\".\"\".\" gender 0..1codemale | female | other | unknown
AdministrativeGender (Required)
\".\"\".\"\".\"\".\" organization I0..1Reference(Organization)Organization that is associated with the contact
\".\"\".\"\".\"\".\" period 0..1PeriodThe period during which this contact person or organization is valid to be contacted relating to this patient
\".\"\".\"\".\" communication 0..*BackboneElementA language which may be used to communicate with the patient about his or her health
\".\"\".\"\".\"\".\" language 1..1CodeableConceptThe language which can be used to communicate with the patient about his or her health
Common Languages (Preferred but limited to AllLanguages)
\".\"\".\"\".\"\".\" preferred 0..1booleanLanguage preference indicator
\".\"\".\"\".\" generalPractitioner 0..*Reference(Organization | Practitioner | PractitionerRole)Patient's nominated primary care provider
\".\"\".\"\".\" managingOrganization Σ0..1Reference(Organization)Organization that is the custodian of the patient record
\".\"\".\"\".\" link ?!Σ0..*BackboneElementLink to another patient resource that concerns the same actual person
\".\"\".\"\".\"\".\" other Σ1..1Reference(Patient | RelatedPerson)The other patient or related person resource that the link refers to
\".\"\".\"\".\"\".\" type Σ1..1codereplaced-by | replaces | refer | seealso
LinkType (Required)

\"doco\" Documentation for this format
" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-category", + "valueString": "Base.Individuals" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm", + "valueInteger": 5 + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-security-category", + "valueCode": "patient" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg", + "valueCode": "pa" + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/Patient", + "version": "4.3.0", + "name": "Patient", + "status": "active", + "experimental": false, + "date": "2022-05-28T12:47:40+10:00", + "publisher": "Health Level Seven International (Patient Administration)", + "contact": [ + { + "telecom": [ + { + "system": "url", + "value": "http://hl7.org/fhir" + } + ] + }, + { + "telecom": [ + { + "system": "url", + "value": "http://www.hl7.org/Special/committees/pafm/index.cfm" + } + ] + } + ], + "description": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", + "purpose": "Tracking patient is the center of the healthcare process.", + "fhirVersion": "4.3.0", + "mapping": [ + { + "identity": "rim", + "uri": "http://hl7.org/v3", + "name": "RIM Mapping" + }, + { + "identity": "cda", + "uri": "http://hl7.org/v3/cda", + "name": "CDA (R2)" + }, + { + "identity": "w5", + "uri": "http://hl7.org/fhir/fivews", + "name": "FiveWs Pattern Mapping" + }, + { + "identity": "v2", + "uri": "http://hl7.org/v2", + "name": "HL7 v2 Mapping" + }, + { + "identity": "loinc", + "uri": "http://loinc.org", + "name": "LOINC code for the element" + } + ], + "kind": "resource", + "abstract": false, + "type": "Patient", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", + "derivation": "specialization", + "snapshot": { + "element": [ + { + "id": "Patient", + "path": "Patient", + "short": "Information about an individual or animal receiving health care services", + "definition": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", + "alias": [ "SubjectOfCare Client Resident" ], + "min": 0, + "max": "*", + "base": { + "path": "Patient", + "min": 0, + "max": "*" + }, + "constraint": [ + { + "key": "dom-2", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL NOT contain nested Resources", + "expression": "contained.contained.empty()", + "xpath": "not(parent::f:contained and f:contained)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-3", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource", + "expression": "contained.where(((id.exists() and ('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url)))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(uri) = '#').exists()).not()).trace('unmatched', id).empty()", + "xpath": "not(exists(for $contained in f:contained return $contained[not(exists(parent::*/descendant::f:reference/@value=concat('#', $contained/*/f:id/@value)) or exists(descendant::f:reference[@value='#']))]))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-4", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated", + "expression": "contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:versionId)) and not(exists(f:contained/*/f:meta/f:lastUpdated))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-5", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a security label", + "expression": "contained.meta.security.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:security))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice", + "valueBoolean": true + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation", + "valueMarkdown": "When a resource has no narrative, only systems that fully understand the data can display the resource to a human safely. Including a human readable representation in the resource makes for a much more robust eco-system and cheaper handling of resources by intermediary systems. Some ecosystems restrict distribution of resources to only those systems that do fully understand the resources, and as a consequence implementers may believe that the narrative is superfluous. However experience shows that such eco-systems often open up to new participants over time." + } + ], + "key": "dom-6", + "severity": "warning", + "human": "A resource should have narrative for robust management", + "expression": "text.`div`.exists()", + "xpath": "exists(f:text/h:div)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Entity. Role, or Act" + }, + { + "identity": "rim", + "map": "Patient[classCode=PAT]" + }, + { + "identity": "cda", + "map": "ClinicalDocument.recordTarget.patientRole" + }, + { + "identity": "w5", + "map": "administrative.individual" + } + ] + }, + { + "id": "Patient.id", + "path": "Patient.id", + "short": "Logical id of this artifact", + "definition": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "comment": "The only time that a resource does not have an id is when it is being submitted to the server using a create operation.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "id" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true + }, + { + "id": "Patient.meta", + "path": "Patient.meta", + "short": "Metadata about the resource", + "definition": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.meta", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Meta" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true + }, + { + "id": "Patient.implicitRules", + "path": "Patient.implicitRules", + "short": "A set of rules under which this content was created", + "definition": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "comment": "Asserting this rule set restricts the content to be only understood by a limited set of trading partners. This inherently limits the usefulness of the data in the long term. However, the existing health eco-system is highly fractured, and not yet ready to define, collect, and exchange data in a generally computable sense. Wherever possible, implementers and/or specification writers should avoid using this element. Often, when used, the URL is a reference to an implementation guide that defines these special rules as part of it's narrative along with other profiles, value sets, etc.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.implicitRules", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "uri" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because the implicit rules may provide additional knowledge about the resource that modifies it's meaning or interpretation", + "isSummary": true + }, + { + "id": "Patient.language", + "path": "Patient.language", + "short": "Language of the resource content", + "definition": "The base language in which the resource is written.", + "comment": "Language is provided to support indexing and accessibility (typically, services such as text to speech use the language tag). The html language tag in the narrative applies to the narrative. The language tag on the resource may be used to specify the language of other presentations generated from the data in the resource. Not all the content has to be in the base language. The Resource.language should not be assumed to apply to the narrative automatically. If a language is specified, it should it also be specified on the div element in the html (see rules in HTML5 for information about the relationship between xml:lang and the html lang attribute).", + "min": 0, + "max": "1", + "base": { + "path": "Resource.language", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + } + }, + { + "id": "Patient.text", + "path": "Patient.text", + "short": "Text summary of the resource, for human interpretation", + "definition": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "comment": "Contained resources do not have narrative. Resources that are not contained SHOULD have a narrative. In some cases, a resource may only have text with little or no additional discrete data (as long as all minOccurs=1 elements are satisfied). This may be necessary for data from legacy systems where information is captured as a \"text blob\" or where text is additionally entered raw or narrated and encoded information is added later.", + "alias": [ + "narrative", + "html", + "xhtml", + "display" + ], + "min": 0, + "max": "1", + "base": { + "path": "DomainResource.text", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Narrative" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Act.text?" + } + ] + }, + { + "id": "Patient.contained", + "path": "Patient.contained", + "short": "Contained, inline Resources", + "definition": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, and nor can they have their own independent transaction scope.", + "comment": "This should never be done when the content can be identified properly, as once identification is lost, it is extremely difficult (and context dependent) to restore it again. Contained resources may have profiles and tags In their meta elements, but SHALL NOT have security labels.", + "alias": [ + "inline resources", + "anonymous resources", + "contained resources" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.contained", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Resource" + } + ], + "constraint": [ + { + "key": "dom-r4b", + "severity": "warning", + "human": "Containing new R4B resources within R4 resources may cause interoperability issues if instances are shared with R4 systems", + "expression": "($this is Citation or $this is Evidence or $this is EvidenceReport or $this is EvidenceVariable or $this is MedicinalProductDefinition or $this is PackagedProductDefinition or $this is AdministrableProductDefinition or $this is Ingredient or $this is ClinicalUseDefinition or $this is RegulatedAuthorization or $this is SubstanceDefinition or $this is SubscriptionStatus or $this is SubscriptionTopic) implies (%resource is Citation or %resource is Evidence or %resource is EvidenceReport or %resource is EvidenceVariable or %resource is MedicinalProductDefinition or %resource is PackagedProductDefinition or %resource is AdministrableProductDefinition or %resource is Ingredient or %resource is ClinicalUseDefinition or %resource is RegulatedAuthorization or %resource is SubstanceDefinition or %resource is SubscriptionStatus or %resource is SubscriptionTopic)", + "xpath": "not(f:Citation|f:Evidence|f:EvidenceReport|f:EvidenceVariable|f:MedicinalProductDefinition|f:PackagedProductDefinition|f:AdministrableProductDefinition|f:Ingredient|f:ClinicalUseDefinition|f:RegulatedAuthorization|f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic) or not(parent::f:Citation|parent::f:Evidence|parent::f:EvidenceReport|parent::f:EvidenceVariable|parent::f:MedicinalProductDefinition|parent::f:PackagedProductDefinition|parent::f:AdministrableProductDefinition|parent::f:Ingredient|parent::f:ClinicalUseDefinition|parent::f:RegulatedAuthorization|parent::f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic)", + "source": "http://hl7.org/fhir/StructureDefinition/Patient" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.extension", + "path": "Patient.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.modifierExtension", + "path": "Patient.modifierExtension", + "short": "Extensions that cannot be ignored", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the resource that contains them", + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.identifier", + "path": "Patient.identifier", + "short": "An identifier for this patient", + "definition": "An identifier for this patient.", + "requirements": "Patients are almost always assigned specific numerical identifiers.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.identifier", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Identifier" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.identifier" + }, + { + "identity": "v2", + "map": "PID-3" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": ".id" + } + ] + }, + { + "id": "Patient.active", + "path": "Patient.active", + "short": "Whether this patient's record is in active use", + "definition": "Whether this patient record is in active use. \nMany systems use this property to mark as non-current patients, such as those that have not been seen for a period of time based on an organization's business rules.\n\nIt is often used to filter patient lists to exclude inactive patients\n\nDeceased patients may also be marked as inactive for the same reasons, but may be active for some time after death.", + "comment": "If a record is inactive, and linked to an active record, then future patient/record updates should occur on the other patient.", + "requirements": "Need to be able to mark a patient record as not to be used because it was created in error.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.active", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "boolean" + } + ], + "meaningWhenMissing": "This resource is generally assumed to be active if no value is provided for the active element", + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labelled as a modifier because it is a status element that can indicate that a record should not be treated as valid", + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.status" + }, + { + "identity": "rim", + "map": "statusCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.name", + "path": "Patient.name", + "short": "A name associated with the patient", + "definition": "A name associated with the individual.", + "comment": "A patient may have multiple names with different uses or applicable periods. For animals, the name is a \"HumanName\" in the sense that is assigned and used by humans and has the same patterns.", + "requirements": "Need to be able to track the patient by multiple names. Examples are your official name and a partner name.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.name", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "HumanName" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-5, PID-9" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": ".patient.name" + } + ] + }, + { + "id": "Patient.telecom", + "path": "Patient.telecom", + "short": "A contact detail for the individual", + "definition": "A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted.", + "comment": "A Patient may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently and also to help with identification. The address might not go directly to the individual, but may reach another party that is able to proxy for the patient (i.e. home phone, or pet owner's phone).", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.telecom", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "ContactPoint" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-13, PID-14, PID-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": ".telecom" + } + ] + }, + { + "id": "Patient.gender", + "path": "Patient.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes.", + "comment": "The gender might not match the biological sex as determined by genetics or the individual's preferred identification. Note that for both humans and particularly animals, there are other legitimate possibilities than male and female, though the vast majority of systems and contexts only support male and female. Systems providing decision support or enforcing business rules should ideally do this on the basis of Observations dealing with the specific sex or gender aspect of interest (anatomical, chromosomal, social, etc.) However, because these observations are infrequently recorded, defaulting to the administrative gender is common practice. Where such defaulting occurs, rule enforcement should allow for the variation between administrative and biological, chromosomal and other gender aspects. For example, an alert about a hysterectomy on a male should be handled as a warning or overridable error, not a \"hard\" error. See the Patient Gender and Sex section for additional information about communicating patient gender and sex.", + "requirements": "Needed for identification of the individual, in combination with (at least) name and birth date.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.gender", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-8" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": ".patient.administrativeGenderCode" + } + ] + }, + { + "id": "Patient.birthDate", + "path": "Patient.birthDate", + "short": "The date of birth for the individual", + "definition": "The date of birth for the individual.", + "comment": "At least an estimated year should be provided as a guess if the real DOB is unknown There is a standard extension \"patient-birthTime\" available that should be used where Time is required (such as in maternity/infant care systems).", + "requirements": "Age of the individual drives many clinical processes.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.birthDate", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "date" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-7" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/birthTime" + }, + { + "identity": "cda", + "map": ".patient.birthTime" + }, + { + "identity": "loinc", + "map": "21112-8" + } + ] + }, + { + "id": "Patient.deceased[x]", + "path": "Patient.deceased[x]", + "short": "Indicates if the individual is deceased or not", + "definition": "Indicates if the individual is deceased or not.", + "comment": "If there's no value in the instance, it means there is no statement on whether or not the individual is deceased. Most systems will interpret the absence of a value as a sign of the person being alive.", + "requirements": "The fact that a patient is deceased influences the clinical process. Also, in human communication and relation management it is necessary to know whether the person is alive.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.deceased[x]", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "boolean" + }, + { + "code": "dateTime" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because once a patient is marked as deceased, the actions that are appropriate to perform on the patient may be significantly different.", + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-30 (bool) and PID-29 (datetime)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.address", + "path": "Patient.address", + "short": "An address for the individual", + "definition": "An address for the individual.", + "comment": "Patient may have multiple addresses with different uses or applicable periods.", + "requirements": "May need to keep track of patient addresses for contacting, billing or reporting requirements and also to help with identification.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.address", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Address" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-11" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": ".addr" + } + ] + }, + { + "id": "Patient.maritalStatus", + "path": "Patient.maritalStatus", + "short": "Marital (civil) status of a patient", + "definition": "This field contains a patient's most recent marital (civil) status.", + "requirements": "Most, if not all systems capture it.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.maritalStatus", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "MaritalStatus" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "extensible", + "description": "The domestic partnership status of a person.", + "valueSet": "http://hl7.org/fhir/ValueSet/marital-status" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-16" + }, + { + "identity": "rim", + "map": "player[classCode=PSN]/maritalStatusCode" + }, + { + "identity": "cda", + "map": ".patient.maritalStatusCode" + } + ] + }, + { + "id": "Patient.multipleBirth[x]", + "path": "Patient.multipleBirth[x]", + "short": "Whether patient is part of a multiple birth", + "definition": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", + "comment": "Where the valueInteger is provided, the number is the birth number in the sequence. E.g. The middle birth in triplets would be valueInteger=2 and the third born would have valueInteger=3 If a boolean value was provided for this triplets example, then all 3 patient records would have valueBoolean=true (the ordering is not indicated).", + "requirements": "For disambiguation of multiple-birth children, especially relevant where the care provider doesn't meet the patient, such as labs.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.multipleBirth[x]", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "boolean" + }, + { + "code": "integer" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-24 (bool), PID-25 (integer)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthOrderNumber" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.photo", + "path": "Patient.photo", + "short": "Image of the patient", + "definition": "Image of the patient.", + "comment": "Guidelines:\n* Use id photos, not clinical photos.\n* Limit dimensions to thumbnail.\n* Keep byte count low to ease resource updates.", + "requirements": "Many EHR systems have the capability to capture an image of the patient. Fits with newer social media usage too.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.photo", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Attachment" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "OBX-5 - needs a profile" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/desc" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name", + "valueString": "Contact" + } + ], + "path": "Patient.contact", + "short": "A contact party (e.g. guardian, partner, friend) for the patient", + "definition": "A contact party (e.g. guardian, partner, friend) for the patient.", + "comment": "Contact covers all kinds of contact parties: family members, business contacts, guardians, caregivers. Not applicable to register pedigree and family ties beyond use of having contact.", + "requirements": "Need to track people you can contact about the patient.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.contact", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "pat-1", + "severity": "error", + "human": "SHALL at least contain a contact's details or a reference to an organization", + "expression": "name.exists() or telecom.exists() or address.exists() or organization.exists()", + "xpath": "exists(f:name) or exists(f:telecom) or exists(f:address) or exists(f:organization)", + "source": "http://hl7.org/fhir/StructureDefinition/Patient" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/scopedRole[classCode=CON]" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.id", + "path": "Patient.contact.id", + "representation": [ "xmlAttr" ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "string" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.extension", + "path": "Patient.contact.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.modifierExtension", + "path": "Patient.contact.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.contact.relationship", + "path": "Patient.contact.relationship", + "short": "The kind of relationship", + "definition": "The nature of the relationship between the patient and the contact person.", + "requirements": "Used to determine which contact person is the most relevant to approach, depending on circumstances.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.contact.relationship", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "ContactRelationship" + } + ], + "strength": "extensible", + "description": "The nature of the relationship between a patient and a contact person for that patient.", + "valueSet": "http://hl7.org/fhir/ValueSet/patient-contactrelationship" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-7, NK1-3" + }, + { + "identity": "rim", + "map": "code" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.name", + "path": "Patient.contact.name", + "short": "A name associated with the contact person", + "definition": "A name associated with the contact person.", + "requirements": "Contact persons need to be identified by name, but it is uncommon to need details about multiple other names for that contact person.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.name", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "HumanName" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-2" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.telecom", + "path": "Patient.contact.telecom", + "short": "A contact detail for the person", + "definition": "A contact detail for the person, e.g. a telephone number or an email address.", + "comment": "Contact may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently, and also to help with identification.", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.contact.telecom", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "ContactPoint" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-5, NK1-6, NK1-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.address", + "path": "Patient.contact.address", + "short": "Address for the contact person", + "definition": "Address for the contact person.", + "requirements": "Need to keep track where the contact person can be contacted per postal mail or visited.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.address", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Address" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-4" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.gender", + "path": "Patient.contact.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the contact person is considered to have for administration and record keeping purposes.", + "requirements": "Needed to address the person correctly.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.gender", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-15" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.organization", + "path": "Patient.contact.organization", + "short": "Organization that is associated with the contact", + "definition": "Organization on behalf of which the contact is acting or for which the contact is working.", + "requirements": "For guardians or business related contacts, the organization is relevant.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.organization", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] + } + ], + "condition": [ "pat-1" ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-13, NK1-30, NK1-31, NK1-32, NK1-41" + }, + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.period", + "path": "Patient.contact.period", + "short": "The period during which this contact person or organization is valid to be contacted relating to this patient", + "definition": "The period during which this contact person or organization is valid to be contacted relating to this patient.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.period", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Period" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "effectiveTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication", + "path": "Patient.communication", + "short": "A language which may be used to communicate with the patient about his or her health", + "definition": "A language which may be used to communicate with the patient about his or her health.", + "comment": "If no language is specified, this *implies* that the default local language is spoken. If you need to convey proficiency for multiple modes, then you need multiple Patient.Communication associations. For animals, language is not a relevant field, and should be absent from the instance. If the Patient does not speak the default local language, then the Interpreter Required Standard can be used to explicitly declare that an interpreter is required.", + "requirements": "If a patient does not speak the local language, interpreters may be required, so languages spoken and proficiency are important things to keep track of both for patient and other persons of interest.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.communication", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "LanguageCommunication" + }, + { + "identity": "cda", + "map": "patient.languageCommunication" + } + ] + }, + { + "id": "Patient.communication.id", + "path": "Patient.communication.id", + "representation": [ "xmlAttr" ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "string" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication.extension", + "path": "Patient.communication.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication.modifierExtension", + "path": "Patient.communication.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.communication.language", + "path": "Patient.communication.language", + "short": "The language which can be used to communicate with the patient about his or her health", + "definition": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-EN\" for England English.", + "comment": "The structure aa-BB with this exact casing is one the most widely used notations for locale. However not all systems actually code this but instead have it as free text. Hence CodeableConcept instead of code as the data type.", + "requirements": "Most systems in multilingual countries will want to convey language. Not all systems actually need the regional dialect.", + "min": 1, + "max": "1", + "base": { + "path": "Patient.communication.language", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-15, LAN-2" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/languageCommunication/code" + }, + { + "identity": "cda", + "map": ".languageCode" + } + ] + }, + { + "id": "Patient.communication.preferred", + "path": "Patient.communication.preferred", + "short": "Language preference indicator", + "definition": "Indicates whether or not the patient prefers this language (over other languages he masters up a certain level).", + "comment": "This language is specifically identified for communicating healthcare information.", + "requirements": "People that master multiple languages up to certain level may prefer one or more, i.e. feel more confident in communicating in a particular language making other languages sort of a fall back method.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.communication.preferred", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "boolean" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-15" + }, + { + "identity": "rim", + "map": "preferenceInd" + }, + { + "identity": "cda", + "map": ".preferenceInd" + } + ] + }, + { + "id": "Patient.generalPractitioner", + "path": "Patient.generalPractitioner", + "short": "Patient's nominated primary care provider", + "definition": "Patient's nominated care provider.", + "comment": "This may be the primary care provider (in a GP context), or it may be a patient nominated care manager in a community/disability setting, or even organization that will provide people to perform the care provider roles. It is not to be used to record Care Teams, these should be in a CareTeam resource that may be linked to the CarePlan or EpisodeOfCare resources.\nMultiple GPs may be recorded against the patient for various reasons, such as a student that has his home GP listed along with the GP at university during the school semesters, or a \"fly-in/fly-out\" worker that has the onsite GP also included with his home GP to remain aware of medical issues.\n\nJurisdictions may decide that they can profile this down to 1 if desired, or 1 per type.", + "alias": [ "careProvider" ], + "min": 0, + "max": "*", + "base": { + "path": "Patient.generalPractitioner", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization", + "http://hl7.org/fhir/StructureDefinition/Practitioner", + "http://hl7.org/fhir/StructureDefinition/PractitionerRole" + ] + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PD1-4" + }, + { + "identity": "rim", + "map": "subjectOf.CareEvent.performer.AssignedEntity" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.managingOrganization", + "path": "Patient.managingOrganization", + "short": "Organization that is the custodian of the patient record", + "definition": "Organization that is the custodian of the patient record.", + "comment": "There is only one managing organization for a specific patient record. Other organizations will have their own Patient record, and may use the Link property to join the records together (or a Person resource which can include confidence ratings for the association).", + "requirements": "Need to know who recognizes this patient record, manages and updates it.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.managingOrganization", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": ".providerOrganization" + } + ] + }, + { + "id": "Patient.link", + "path": "Patient.link", + "short": "Link to another patient resource that concerns the same actual person", + "definition": "Link to another patient resource that concerns the same actual patient.", + "comment": "There is no assumption that linked patient records have mutual links.", + "requirements": "There are multiple use cases: \n\n* Duplicate patient records due to the clerical errors associated with the difficulties of identifying humans consistently, and \n* Distribution of patient information across multiple servers.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.link", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because it might not be the main Patient resource, and the referenced patient should be used instead of this Patient record. This is when the link.type value is 'replaced-by'", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "outboundLink" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.id", + "path": "Patient.link.id", + "representation": [ "xmlAttr" ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "string" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.extension", + "path": "Patient.link.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.modifierExtension", + "path": "Patient.link.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.link.other", + "path": "Patient.link.other", + "short": "The other patient or related person resource that the link refers to", + "definition": "The other patient resource that the link refers to.", + "comment": "Referencing a RelatedPerson here removes the need to use a Person record to associate a Patient and RelatedPerson as the same individual.", + "min": 1, + "max": "1", + "base": { + "path": "Patient.link.other", + "min": 1, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy", + "valueBoolean": false + } + ], + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Patient", + "http://hl7.org/fhir/StructureDefinition/RelatedPerson" + ] + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-3, MRG-1" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.type", + "path": "Patient.link.type", + "short": "replaced-by | replaces | refer | seealso", + "definition": "The type of link between this patient resource and another patient resource.", + "min": 1, + "max": "1", + "base": { + "path": "Patient.link.type", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "LinkType" + } + ], + "strength": "required", + "description": "The type of link between this patient resource and another patient resource.", + "valueSet": "http://hl7.org/fhir/ValueSet/link-type|4.3.0" + }, + "mapping": [ + { + "identity": "rim", + "map": "typeCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + } + ] + }, + "differential": { + "element": [ + { + "id": "Patient", + "path": "Patient", + "short": "Information about an individual or animal receiving health care services", + "definition": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", + "alias": [ "SubjectOfCare Client Resident" ], + "min": 0, + "max": "*", + "mustSupport": false, + "isModifier": false, + "mapping": [ + { + "identity": "rim", + "map": "Patient[classCode=PAT]" + }, + { + "identity": "cda", + "map": "ClinicalDocument.recordTarget.patientRole" + }, + { + "identity": "w5", + "map": "administrative.individual" + } + ] + }, + { + "id": "Patient.identifier", + "path": "Patient.identifier", + "short": "An identifier for this patient", + "definition": "An identifier for this patient.", + "requirements": "Patients are almost always assigned specific numerical identifiers.", + "min": 0, + "max": "*", + "type": [ + { + "code": "Identifier" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.identifier" + }, + { + "identity": "v2", + "map": "PID-3" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": ".id" + } + ] + }, + { + "id": "Patient.active", + "path": "Patient.active", + "short": "Whether this patient's record is in active use", + "definition": "Whether this patient record is in active use. \nMany systems use this property to mark as non-current patients, such as those that have not been seen for a period of time based on an organization's business rules.\n\nIt is often used to filter patient lists to exclude inactive patients\n\nDeceased patients may also be marked as inactive for the same reasons, but may be active for some time after death.", + "comment": "If a record is inactive, and linked to an active record, then future patient/record updates should occur on the other patient.", + "requirements": "Need to be able to mark a patient record as not to be used because it was created in error.", + "min": 0, + "max": "1", + "type": [ + { + "code": "boolean" + } + ], + "meaningWhenMissing": "This resource is generally assumed to be active if no value is provided for the active element", + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labelled as a modifier because it is a status element that can indicate that a record should not be treated as valid", + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.status" + }, + { + "identity": "rim", + "map": "statusCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.name", + "path": "Patient.name", + "short": "A name associated with the patient", + "definition": "A name associated with the individual.", + "comment": "A patient may have multiple names with different uses or applicable periods. For animals, the name is a \"HumanName\" in the sense that is assigned and used by humans and has the same patterns.", + "requirements": "Need to be able to track the patient by multiple names. Examples are your official name and a partner name.", + "min": 0, + "max": "*", + "type": [ + { + "code": "HumanName" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-5, PID-9" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": ".patient.name" + } + ] + }, + { + "id": "Patient.telecom", + "path": "Patient.telecom", + "short": "A contact detail for the individual", + "definition": "A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted.", + "comment": "A Patient may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently and also to help with identification. The address might not go directly to the individual, but may reach another party that is able to proxy for the patient (i.e. home phone, or pet owner's phone).", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "type": [ + { + "code": "ContactPoint" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-13, PID-14, PID-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": ".telecom" + } + ] + }, + { + "id": "Patient.gender", + "path": "Patient.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes.", + "comment": "The gender might not match the biological sex as determined by genetics or the individual's preferred identification. Note that for both humans and particularly animals, there are other legitimate possibilities than male and female, though the vast majority of systems and contexts only support male and female. Systems providing decision support or enforcing business rules should ideally do this on the basis of Observations dealing with the specific sex or gender aspect of interest (anatomical, chromosomal, social, etc.) However, because these observations are infrequently recorded, defaulting to the administrative gender is common practice. Where such defaulting occurs, rule enforcement should allow for the variation between administrative and biological, chromosomal and other gender aspects. For example, an alert about a hysterectomy on a male should be handled as a warning or overridable error, not a \"hard\" error. See the Patient Gender and Sex section for additional information about communicating patient gender and sex.", + "requirements": "Needed for identification of the individual, in combination with (at least) name and birth date.", + "min": 0, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-8" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": ".patient.administrativeGenderCode" + } + ] + }, + { + "id": "Patient.birthDate", + "path": "Patient.birthDate", + "short": "The date of birth for the individual", + "definition": "The date of birth for the individual.", + "comment": "At least an estimated year should be provided as a guess if the real DOB is unknown There is a standard extension \"patient-birthTime\" available that should be used where Time is required (such as in maternity/infant care systems).", + "requirements": "Age of the individual drives many clinical processes.", + "min": 0, + "max": "1", + "type": [ + { + "code": "date" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-7" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/birthTime" + }, + { + "identity": "cda", + "map": ".patient.birthTime" + }, + { + "identity": "loinc", + "map": "21112-8" + } + ] + }, + { + "id": "Patient.deceased[x]", + "path": "Patient.deceased[x]", + "short": "Indicates if the individual is deceased or not", + "definition": "Indicates if the individual is deceased or not.", + "comment": "If there's no value in the instance, it means there is no statement on whether or not the individual is deceased. Most systems will interpret the absence of a value as a sign of the person being alive.", + "requirements": "The fact that a patient is deceased influences the clinical process. Also, in human communication and relation management it is necessary to know whether the person is alive.", + "min": 0, + "max": "1", + "type": [ + { + "code": "boolean" + }, + { + "code": "dateTime" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because once a patient is marked as deceased, the actions that are appropriate to perform on the patient may be significantly different.", + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-30 (bool) and PID-29 (datetime)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.address", + "path": "Patient.address", + "short": "An address for the individual", + "definition": "An address for the individual.", + "comment": "Patient may have multiple addresses with different uses or applicable periods.", + "requirements": "May need to keep track of patient addresses for contacting, billing or reporting requirements and also to help with identification.", + "min": 0, + "max": "*", + "type": [ + { + "code": "Address" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-11" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": ".addr" + } + ] + }, + { + "id": "Patient.maritalStatus", + "path": "Patient.maritalStatus", + "short": "Marital (civil) status of a patient", + "definition": "This field contains a patient's most recent marital (civil) status.", + "requirements": "Most, if not all systems capture it.", + "min": 0, + "max": "1", + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "MaritalStatus" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "extensible", + "description": "The domestic partnership status of a person.", + "valueSet": "http://hl7.org/fhir/ValueSet/marital-status" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-16" + }, + { + "identity": "rim", + "map": "player[classCode=PSN]/maritalStatusCode" + }, + { + "identity": "cda", + "map": ".patient.maritalStatusCode" + } + ] + }, + { + "id": "Patient.multipleBirth[x]", + "path": "Patient.multipleBirth[x]", + "short": "Whether patient is part of a multiple birth", + "definition": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", + "comment": "Where the valueInteger is provided, the number is the birth number in the sequence. E.g. The middle birth in triplets would be valueInteger=2 and the third born would have valueInteger=3 If a boolean value was provided for this triplets example, then all 3 patient records would have valueBoolean=true (the ordering is not indicated).", + "requirements": "For disambiguation of multiple-birth children, especially relevant where the care provider doesn't meet the patient, such as labs.", + "min": 0, + "max": "1", + "type": [ + { + "code": "boolean" + }, + { + "code": "integer" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-24 (bool), PID-25 (integer)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthOrderNumber" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.photo", + "path": "Patient.photo", + "short": "Image of the patient", + "definition": "Image of the patient.", + "comment": "Guidelines:\n* Use id photos, not clinical photos.\n* Limit dimensions to thumbnail.\n* Keep byte count low to ease resource updates.", + "requirements": "Many EHR systems have the capability to capture an image of the patient. Fits with newer social media usage too.", + "min": 0, + "max": "*", + "type": [ + { + "code": "Attachment" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "OBX-5 - needs a profile" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/desc" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name", + "valueString": "Contact" + } + ], + "path": "Patient.contact", + "short": "A contact party (e.g. guardian, partner, friend) for the patient", + "definition": "A contact party (e.g. guardian, partner, friend) for the patient.", + "comment": "Contact covers all kinds of contact parties: family members, business contacts, guardians, caregivers. Not applicable to register pedigree and family ties beyond use of having contact.", + "requirements": "Need to track people you can contact about the patient.", + "min": 0, + "max": "*", + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "pat-1", + "severity": "error", + "human": "SHALL at least contain a contact's details or a reference to an organization", + "expression": "name.exists() or telecom.exists() or address.exists() or organization.exists()", + "xpath": "exists(f:name) or exists(f:telecom) or exists(f:address) or exists(f:organization)", + "source": "http://hl7.org/fhir/StructureDefinition/Patient" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/scopedRole[classCode=CON]" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.relationship", + "path": "Patient.contact.relationship", + "short": "The kind of relationship", + "definition": "The nature of the relationship between the patient and the contact person.", + "requirements": "Used to determine which contact person is the most relevant to approach, depending on circumstances.", + "min": 0, + "max": "*", + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "ContactRelationship" + } + ], + "strength": "extensible", + "description": "The nature of the relationship between a patient and a contact person for that patient.", + "valueSet": "http://hl7.org/fhir/ValueSet/patient-contactrelationship" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-7, NK1-3" + }, + { + "identity": "rim", + "map": "code" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.name", + "path": "Patient.contact.name", + "short": "A name associated with the contact person", + "definition": "A name associated with the contact person.", + "requirements": "Contact persons need to be identified by name, but it is uncommon to need details about multiple other names for that contact person.", + "min": 0, + "max": "1", + "type": [ + { + "code": "HumanName" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-2" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.telecom", + "path": "Patient.contact.telecom", + "short": "A contact detail for the person", + "definition": "A contact detail for the person, e.g. a telephone number or an email address.", + "comment": "Contact may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently, and also to help with identification.", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "type": [ + { + "code": "ContactPoint" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-5, NK1-6, NK1-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.address", + "path": "Patient.contact.address", + "short": "Address for the contact person", + "definition": "Address for the contact person.", + "requirements": "Need to keep track where the contact person can be contacted per postal mail or visited.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Address" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-4" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.gender", + "path": "Patient.contact.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the contact person is considered to have for administration and record keeping purposes.", + "requirements": "Needed to address the person correctly.", + "min": 0, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-15" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.organization", + "path": "Patient.contact.organization", + "short": "Organization that is associated with the contact", + "definition": "Organization on behalf of which the contact is acting or for which the contact is working.", + "requirements": "For guardians or business related contacts, the organization is relevant.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] + } + ], + "condition": [ "pat-1" ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-13, NK1-30, NK1-31, NK1-32, NK1-41" + }, + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.period", + "path": "Patient.contact.period", + "short": "The period during which this contact person or organization is valid to be contacted relating to this patient", + "definition": "The period during which this contact person or organization is valid to be contacted relating to this patient.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Period" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "effectiveTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication", + "path": "Patient.communication", + "short": "A language which may be used to communicate with the patient about his or her health", + "definition": "A language which may be used to communicate with the patient about his or her health.", + "comment": "If no language is specified, this *implies* that the default local language is spoken. If you need to convey proficiency for multiple modes, then you need multiple Patient.Communication associations. For animals, language is not a relevant field, and should be absent from the instance. If the Patient does not speak the default local language, then the Interpreter Required Standard can be used to explicitly declare that an interpreter is required.", + "requirements": "If a patient does not speak the local language, interpreters may be required, so languages spoken and proficiency are important things to keep track of both for patient and other persons of interest.", + "min": 0, + "max": "*", + "type": [ + { + "code": "BackboneElement" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "LanguageCommunication" + }, + { + "identity": "cda", + "map": "patient.languageCommunication" + } + ] + }, + { + "id": "Patient.communication.language", + "path": "Patient.communication.language", + "short": "The language which can be used to communicate with the patient about his or her health", + "definition": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-EN\" for England English.", + "comment": "The structure aa-BB with this exact casing is one the most widely used notations for locale. However not all systems actually code this but instead have it as free text. Hence CodeableConcept instead of code as the data type.", + "requirements": "Most systems in multilingual countries will want to convey language. Not all systems actually need the regional dialect.", + "min": 1, + "max": "1", + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-15, LAN-2" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/languageCommunication/code" + }, + { + "identity": "cda", + "map": ".languageCode" + } + ] + }, + { + "id": "Patient.communication.preferred", + "path": "Patient.communication.preferred", + "short": "Language preference indicator", + "definition": "Indicates whether or not the patient prefers this language (over other languages he masters up a certain level).", + "comment": "This language is specifically identified for communicating healthcare information.", + "requirements": "People that master multiple languages up to certain level may prefer one or more, i.e. feel more confident in communicating in a particular language making other languages sort of a fall back method.", + "min": 0, + "max": "1", + "type": [ + { + "code": "boolean" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-15" + }, + { + "identity": "rim", + "map": "preferenceInd" + }, + { + "identity": "cda", + "map": ".preferenceInd" + } + ] + }, + { + "id": "Patient.generalPractitioner", + "path": "Patient.generalPractitioner", + "short": "Patient's nominated primary care provider", + "definition": "Patient's nominated care provider.", + "comment": "This may be the primary care provider (in a GP context), or it may be a patient nominated care manager in a community/disability setting, or even organization that will provide people to perform the care provider roles. It is not to be used to record Care Teams, these should be in a CareTeam resource that may be linked to the CarePlan or EpisodeOfCare resources.\nMultiple GPs may be recorded against the patient for various reasons, such as a student that has his home GP listed along with the GP at university during the school semesters, or a \"fly-in/fly-out\" worker that has the onsite GP also included with his home GP to remain aware of medical issues.\n\nJurisdictions may decide that they can profile this down to 1 if desired, or 1 per type.", + "alias": [ "careProvider" ], + "min": 0, + "max": "*", + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization", + "http://hl7.org/fhir/StructureDefinition/Practitioner", + "http://hl7.org/fhir/StructureDefinition/PractitionerRole" + ] + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PD1-4" + }, + { + "identity": "rim", + "map": "subjectOf.CareEvent.performer.AssignedEntity" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.managingOrganization", + "path": "Patient.managingOrganization", + "short": "Organization that is the custodian of the patient record", + "definition": "Organization that is the custodian of the patient record.", + "comment": "There is only one managing organization for a specific patient record. Other organizations will have their own Patient record, and may use the Link property to join the records together (or a Person resource which can include confidence ratings for the association).", + "requirements": "Need to know who recognizes this patient record, manages and updates it.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": ".providerOrganization" + } + ] + }, + { + "id": "Patient.link", + "path": "Patient.link", + "short": "Link to another patient resource that concerns the same actual person", + "definition": "Link to another patient resource that concerns the same actual patient.", + "comment": "There is no assumption that linked patient records have mutual links.", + "requirements": "There are multiple use cases: \n\n* Duplicate patient records due to the clerical errors associated with the difficulties of identifying humans consistently, and \n* Distribution of patient information across multiple servers.", + "min": 0, + "max": "*", + "type": [ + { + "code": "BackboneElement" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because it might not be the main Patient resource, and the referenced patient should be used instead of this Patient record. This is when the link.type value is 'replaced-by'", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "outboundLink" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.other", + "path": "Patient.link.other", + "short": "The other patient or related person resource that the link refers to", + "definition": "The other patient resource that the link refers to.", + "comment": "Referencing a RelatedPerson here removes the need to use a Person record to associate a Patient and RelatedPerson as the same individual.", + "min": 1, + "max": "1", + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy", + "valueBoolean": false + } + ], + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Patient", + "http://hl7.org/fhir/StructureDefinition/RelatedPerson" + ] + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-3, MRG-1" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.type", + "path": "Patient.link.type", + "short": "replaced-by | replaces | refer | seealso", + "definition": "The type of link between this patient resource and another patient resource.", + "min": 1, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "LinkType" + } + ], + "strength": "required", + "description": "The type of link between this patient resource and another patient resource.", + "valueSet": "http://hl7.org/fhir/ValueSet/link-type|4.3.0" + }, + "mapping": [ + { + "identity": "rim", + "map": "typeCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + } + ] + } +} diff --git a/TestSourceGen/Program.cs b/TestSourceGen/Program.cs new file mode 100644 index 000000000..c7a44b6c9 --- /dev/null +++ b/TestSourceGen/Program.cs @@ -0,0 +1,26 @@ +// See https://aka.ms/new-console-template for more information + +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.Health.Fhir.SourceGenerator; +using Microsoft.Health.Fhir.SpecManager.Converters; +using Microsoft.Health.Fhir.SpecManager.Language; +using Microsoft.Health.Fhir.SpecManager.Manager; + +var generator = new FhirSourceGenerator(); + +var fhirConverter = ConverterHelper.ConverterForVersion(FhirPackageCommon.FhirSequenceEnum.R4B); + +var fhirInfo = new FhirVersionInfo(FhirPackageCommon.FhirSequenceEnum.R4B); + +var complex = generator.ProcessFile("Patient.StructureDefinition.json", fhirInfo, fhirConverter, out var fileName, out var canonical, out var artifactClass); + +ILanguage language = LanguageHelper.GetLanguages("CSharpFirely2")[0]; +using var memoryStream = new MemoryStream(short.MaxValue); +language.Export(fhirInfo, complex, memoryStream); + +memoryStream.Seek(0, SeekOrigin.Begin); +StreamReader reader = new StreamReader(memoryStream, Encoding.UTF8); +var code = await reader.ReadToEndAsync(); + +Console.WriteLine(code); diff --git a/TestSourceGen/TestSourceGen.csproj b/TestSourceGen/TestSourceGen.csproj new file mode 100644 index 000000000..48131c5c6 --- /dev/null +++ b/TestSourceGen/TestSourceGen.csproj @@ -0,0 +1,27 @@ + + + + Exe + net6.0 + enable + enable + + + + + PreserveNewest + + + + + + + + + + + + + + + diff --git a/fhir-codegen.sln b/fhir-codegen.sln index ba494120c..73040eb00 100644 --- a/fhir-codegen.sln +++ b/fhir-codegen.sln @@ -32,6 +32,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Fhir.CodeG EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FhirCodeGenBlazor", "src\FhirCodeGenBlazor\FhirCodeGenBlazor.csproj", "{F91764FD-EE86-4FBC-951F-819361ABCA4F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleSourceGen", "SampleSourceGen\SampleSourceGen.csproj", "{08CA896F-B304-4B08-A35A-F6D64C166AF7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Fhir.SourceGenerator", "src\Microsoft.Health.Fhir.SourceGenerator\Microsoft.Health.Fhir.SourceGenerator.csproj", "{213EE0DD-ECE8-47AF-8301-42BEAE4EFE54}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestSourceGen", "TestSourceGen\TestSourceGen.csproj", "{956E4954-BBC8-4471-B53C-9424F1FE681A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -62,6 +68,18 @@ Global {F91764FD-EE86-4FBC-951F-819361ABCA4F}.Debug|Any CPU.Build.0 = Debug|Any CPU {F91764FD-EE86-4FBC-951F-819361ABCA4F}.Release|Any CPU.ActiveCfg = Release|Any CPU {F91764FD-EE86-4FBC-951F-819361ABCA4F}.Release|Any CPU.Build.0 = Release|Any CPU + {08CA896F-B304-4B08-A35A-F6D64C166AF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08CA896F-B304-4B08-A35A-F6D64C166AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08CA896F-B304-4B08-A35A-F6D64C166AF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08CA896F-B304-4B08-A35A-F6D64C166AF7}.Release|Any CPU.Build.0 = Release|Any CPU + {213EE0DD-ECE8-47AF-8301-42BEAE4EFE54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {213EE0DD-ECE8-47AF-8301-42BEAE4EFE54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {213EE0DD-ECE8-47AF-8301-42BEAE4EFE54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {213EE0DD-ECE8-47AF-8301-42BEAE4EFE54}.Release|Any CPU.Build.0 = Release|Any CPU + {956E4954-BBC8-4471-B53C-9424F1FE681A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {956E4954-BBC8-4471-B53C-9424F1FE681A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {956E4954-BBC8-4471-B53C-9424F1FE681A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {956E4954-BBC8-4471-B53C-9424F1FE681A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Microsoft.Health.Fhir.CodeGenCommon/Extensions/FhirNameConventionExtensions.cs b/src/Microsoft.Health.Fhir.CodeGenCommon/Extensions/FhirNameConventionExtensions.cs index 0408d86e9..4670e0c29 100644 --- a/src/Microsoft.Health.Fhir.CodeGenCommon/Extensions/FhirNameConventionExtensions.cs +++ b/src/Microsoft.Health.Fhir.CodeGenCommon/Extensions/FhirNameConventionExtensions.cs @@ -14,7 +14,7 @@ public static class FhirNameConventionExtensions private static readonly char[] _wordDelimiters = new char[] { ' ', '.', '_', '-' }; /// (Immutable) Options for controlling the word split. - private static readonly StringSplitOptions _wordSplitOptions = StringSplitOptions.RemoveEmptyEntries & StringSplitOptions.TrimEntries; + private static readonly StringSplitOptions _wordSplitOptions = StringSplitOptions.RemoveEmptyEntries; /// A string extension method that converts a word to PascalCase. /// The word to act on. @@ -30,7 +30,7 @@ public static string ToPascalCase(this string word, bool removeDelimiters = true if (removeDelimiters) { - return string.Join(joinDelimiter, word.Split(_wordDelimiters, _wordSplitOptions).Select(w => w.ToPascalCase(false))); + return string.Join(joinDelimiter, word.Split(_wordDelimiters, _wordSplitOptions).Select(w => w.ToPascalCase(false).Trim())); } return string.Concat(word.Substring(0, 1).ToUpperInvariant(), word.Substring(1)); @@ -176,7 +176,7 @@ public static string ToUpperCase(this string word, bool removeDelimiters = true, if (removeDelimiters) { - return string.Join(joinDelimiter, word.Split(_wordDelimiters, _wordSplitOptions).Select(w => w.ToUpperInvariant())); + return string.Join(joinDelimiter, word.Split(_wordDelimiters, _wordSplitOptions).Select(w => w.ToUpperInvariant().Trim())); } return word.ToUpperInvariant(); @@ -256,7 +256,7 @@ public static string ToLowerCase(this string word, bool removeDelimiters = true, if (removeDelimiters) { - return string.Join(joinDelimiter, word.Split(_wordDelimiters, _wordSplitOptions).Select(w => w.ToLowerInvariant())); + return string.Join(joinDelimiter, word.Split(_wordDelimiters, _wordSplitOptions).Select(w => w.ToLowerInvariant().Trim())); } return word.ToLowerInvariant(); @@ -386,7 +386,7 @@ public static string ToPascalDotCase(this string word) return string.Empty; } - return string.Join('.', word.Split(_wordDelimiters, _wordSplitOptions).Select(w => w.ToPascalCase(false))); + return string.Join(".", word.Split(_wordDelimiters, _wordSplitOptions).Select(w => w.ToPascalCase(false).Trim())); } /// A string extension method that converts this object to a pascal dot case. @@ -422,6 +422,6 @@ public static string ToPascalDotCaseWord(this IEnumerable words) return string.Empty; } - return string.Join('.', words.Select(w => w.ToPascalDotCase())); + return string.Join(".", words.Select(w => w.ToPascalDotCase())); } } diff --git a/src/Microsoft.Health.Fhir.CodeGenCommon/Microsoft.Health.Fhir.CodeGenCommon.csproj b/src/Microsoft.Health.Fhir.CodeGenCommon/Microsoft.Health.Fhir.CodeGenCommon.csproj index af9c92919..78f7cf49d 100644 --- a/src/Microsoft.Health.Fhir.CodeGenCommon/Microsoft.Health.Fhir.CodeGenCommon.csproj +++ b/src/Microsoft.Health.Fhir.CodeGenCommon/Microsoft.Health.Fhir.CodeGenCommon.csproj @@ -1,9 +1,23 @@ - + - net7.0 + net7.0;netstandard2.0 + 11 2.0.0-beta1 enable + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + diff --git a/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirComplex.cs b/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirComplex.cs index 3541f481f..c94f5609b 100644 --- a/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirComplex.cs +++ b/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirComplex.cs @@ -762,7 +762,7 @@ public FhirComplex DeepCopy( Dictionary serverOperations = null, bool includeExperimental = false) { - List contextElements = ContextElements?.Select(s => new string(s)).ToList() ?? null; + List contextElements = ContextElements?.ToList() ?? null; // generate our base copy FhirComplex complex = new FhirComplex( diff --git a/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirOperation.cs b/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirOperation.cs index 7ddc39e79..5abd5e1bc 100644 --- a/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirOperation.cs +++ b/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirOperation.cs @@ -159,7 +159,7 @@ public object Clone() { foreach (string resourceType in ResourceTypes) { - resourceTypes.Add(new string(resourceType)); + resourceTypes.Add(resourceType); } } diff --git a/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirUtils.cs b/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirUtils.cs index e7f8852fa..cce85b986 100644 --- a/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirUtils.cs +++ b/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirUtils.cs @@ -650,12 +650,9 @@ public static string SanitizeForProperty( return value; } - [GeneratedRegex("__+")] - private static partial Regex RegexRemoveDuplicateLines(); + private static Regex RegexRemoveDuplicateLines() => new Regex("__+", RegexOptions.Compiled); - [GeneratedRegex("\\s+")] - private static partial Regex RegexRemoveDuplicateWhitespace(); + private static Regex RegexRemoveDuplicateWhitespace() => new Regex("\\s+", RegexOptions.Compiled); - [GeneratedRegex("[^ -~]+")] - private static partial Regex RegexAsciiEscapingR(); + private static Regex RegexAsciiEscapingR() => new Regex("[^ -~]+", RegexOptions.Compiled); } diff --git a/src/Microsoft.Health.Fhir.CodeGenCommon/Shim.cs b/src/Microsoft.Health.Fhir.CodeGenCommon/Shim.cs new file mode 100644 index 000000000..b7af4a887 --- /dev/null +++ b/src/Microsoft.Health.Fhir.CodeGenCommon/Shim.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Health.Fhir.CodeGenCommon; + +internal static class Shim +{ + public static bool StartsWith(this string value, char ch) + { + return value.AsSpan()[0] == ch; + } + + public static int IndexOf(this string value, char ch, StringComparison stringComparison) + { + return value.IndexOf(ch); + } + + public static bool Contains(this string value, char ch, StringComparison stringComparison) + { + return value.Contains(ch); + } + + public static bool Contains(this string value, string substring, StringComparison stringComparison) + { + return value.Contains(substring); + } + + public static string Replace(this string value, string oldSubstring, string replacement, StringComparison stringComparison) + { + return value.Replace(oldSubstring, replacement); + } + + public static string AsSpan(this string value, int start) + => value.Substring(start); + + public static HashSet ToHashSet(this IEnumerable source) + => new HashSet(source); + + public static void Deconstruct(this KeyValuePair pair, out TKey key, out TValue value) + { + key = pair.Key; + value = pair.Value; + } +} diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs new file mode 100644 index 000000000..aa3303d51 --- /dev/null +++ b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs @@ -0,0 +1,136 @@ +using System.Reflection; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using Microsoft.Health.Fhir.CodeGenCommon.Models; +using Microsoft.Health.Fhir.SpecManager.Converters; +using Microsoft.Health.Fhir.SpecManager.Language; +using Microsoft.Health.Fhir.SpecManager.Manager; + +namespace Microsoft.Health.Fhir.SourceGenerator +{ + [Generator] + public class FhirSourceGenerator : ISourceGenerator + { + private static readonly DiagnosticDescriptor FailedParsingStructureDef = new( + "FHIRGEN001", + "Invalid .StructureDefinition.json file", + "Unable to parse StructureDefinition file '{0}'. It must be a valid StructureDefinition file with a snapshot.", + "FhirSourceGenerator", + DiagnosticSeverity.Warning, + true); + + private static readonly DiagnosticDescriptor TypeLoaderException = new( + "FHIRGEN002", + "Fatal FhirCode Generation error", + "Type loader exception '{0}'.", + "FhirSourceGenerator", + DiagnosticSeverity.Error, + true); + + private static readonly DiagnosticDescriptor UnhandledException = new( + "FHIRGEN003", + "Fatal FhirCode Generation error", + "Unhandled exception '{0}'.", + "FhirSourceGenerator", + DiagnosticSeverity.Error, + true); + + private static readonly DiagnosticDescriptor FailedToGenerate = new( + "FHIRGEN004", + "Invalid .StructureDefinition.json file", + "Failed to generate code for json file [{0}]{1}.", + "FhirSourceGenerator", + DiagnosticSeverity.Error, + true); + + private static readonly DiagnosticDescriptor ProcessSuccess = new( + "FHIRGEN005", + "Parsing success", + "Canonical: {0}, Artifact Type: {1}, ResourceCount: {2}", + "FhirSourceGenerator", + DiagnosticSeverity.Warning, + true); + + public void Execute(GeneratorExecutionContext context) + { + try + { + var fhirConverter = ConverterHelper.ConverterForVersion(FhirPackageCommon.FhirSequenceEnum.R4B); + + var fhirInfo = new FhirVersionInfo(FhirPackageCommon.FhirSequenceEnum.R4B); + ILanguage language = LanguageHelper.GetLanguages("CSharpFirely2")[0]; + foreach (var structureDef in context.AdditionalFiles.Where(f => f.Path.EndsWith(".StructureDefinition.json", StringComparison.InvariantCultureIgnoreCase))) + { + if (structureDef is null) + { + continue; + } + + var complex = ProcessFile(structureDef.Path, fhirInfo, fhirConverter, out var fileName, out var canonical, out var artifactClass); + if (complex == null) + { + context.ReportDiagnostic(Diagnostic.Create(FailedParsingStructureDef, Location.None, structureDef.Path)); + continue; + } + + context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, canonical, artifactClass, fhirInfo.Resources.Count)); + + using var memoryStream = new MemoryStream(); + language.Export(fhirInfo, complex, memoryStream); + memoryStream.Position = 0; + + if (memoryStream.Length == 0) + { + context.ReportDiagnostic(Diagnostic.Create(FailedToGenerate, Location.None, structureDef.Path)); + continue; + } + + var code = Encoding.UTF8.GetString(memoryStream.ToArray()); + + context.AddSource($"{fileName}.gen.cs", SourceText.From(code, Encoding.UTF8)); + } + + } + catch (ReflectionTypeLoadException rex) + { + context.ReportDiagnostic(Diagnostic.Create(TypeLoaderException, Location.None, rex.LoaderExceptions)); + } + catch (Exception ex) + { + context.ReportDiagnostic(Diagnostic.Create(UnhandledException, Location.None, ex.StackTrace.Replace(Environment.NewLine, ""))); + } + } + + public void Initialize(GeneratorInitializationContext context) + { + } + + internal FhirComplex? ProcessFile(string path, FhirVersionInfo fhirInfo, IFhirConverter fhirConverter, out string fileName, out string? canonical, out FhirArtifactClassEnum artifactClass) + { + fileName = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path)); + + if (!File.Exists(path)) + { + canonical = null; + artifactClass = default; + return null; + } + + var json = File.ReadAllText(path); + + if (!fhirConverter.TryParseResource(json, out var resource, out var resourceType)) + { + canonical = null; + artifactClass = default; + //context.ReportDiagnostic(Diagnostic.Create(FailedParsingStructureDef, Location.None, path, json)); + return null; + } + + fhirInfo.ProcessResource(resource, out canonical, out artifactClass); + + fhirInfo.Resources.TryGetValue(fileName, out var complex); + return complex; + } + } +} diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj b/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj new file mode 100644 index 000000000..f6972495d --- /dev/null +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj @@ -0,0 +1,70 @@ + + + + netstandard2.0 + 11 + true + enable + true + true + + 0.1.0-beta1 + true + analyzers\cs + embedded + true + + + + + + + + + + + + + + + + + + + + + + + + + + $(GetTargetPathDependsOn);GetDependencyTargetPaths + + + + + + + + + + + + + + + + + true + fhirCsR2.dll + + + true + Microsoft.Health.Fhir.CodeGenCommon.dll + + + true + Microsoft.Health.Fhir.SpecManager.dll + + + diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharp2.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharp2.cs index fe84a0613..f26dcb17f 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharp2.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharp2.cs @@ -275,6 +275,12 @@ public sealed class CSharp2 : ILanguage { "access-modifier", "Access modifier for exported elements (public|internal|private)." }, }; + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpBasic.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpBasic.cs index cad52ac96..8a545c0bb 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpBasic.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpBasic.cs @@ -245,6 +245,12 @@ public sealed class CSharpBasic : ILanguage { "namespace", "Namespace to use when exporting C# files (default: fhir)." }, }; + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs index 5112af5df..9943df9fb 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs @@ -3,6 +3,8 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // using System.IO; +using System.Runtime.InteropServices.ComTypes; +using Microsoft.Extensions.Options; using Microsoft.Health.Fhir.SpecManager.Manager; using Ncqa.Cql.Model; @@ -405,6 +407,22 @@ private enum GenSubset private ModelInfo _cqlModelInfo = null; private IDictionary _cqlModelClassInfo = null; + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + { + using var infoWriter = new ExportStreamWriter(outputStream, Encoding.UTF8, 1024, true); + _modelWriter = infoWriter; + _info = info; + + _options = new ExporterOptions(_languageName, Array.Empty(), new List(), ExporterOptions.ExtensionSupportLevel.All, Array.Empty(), Array.Empty(), new Dictionary(), null, false, true, null); + //_exportDirectory = exportDirectory; + + var dummy = new Dictionary(); + WriteResource(complex, ref dummy, GenSubset.Satellite, infoWriter); + } + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. @@ -808,7 +826,7 @@ private void WriteSearchParameters() string urlComponent = $", Url = \"{sp.URL}\""; string[] components = sp.Components?.Select(c => $"""new SearchParamComponent("{c.Definition}", "{c.Expression}")""").ToArray() ?? Array.Empty(); - string strComponents = (components.Length > 0) ? $", Component = new SearchParamComponent[] {{ {string.Join(',', components)} }}" : string.Empty; + string strComponents = (components.Length > 0) ? $", Component = new SearchParamComponent[] {{ {string.Join(",", components)} }}" : string.Empty; _writer.WriteLineIndented( $"new SearchParamDefinition() " + @@ -1045,7 +1063,21 @@ private void WriteResource( GenSubset subset) { string exportName = complex.NameForExport(FhirTypeBase.NamingConvention.PascalCase); + string filename = Path.Combine(_exportDirectory, "Generated", $"{exportName}.cs"); + using (FileStream stream = new FileStream(filename, FileMode.Create)) + using (ExportStreamWriter writer = new ExportStreamWriter(stream)) + { + WriteResource(complex, ref writtenModels, subset, writer); + } + } + private void WriteResource( + FhirComplex complex, + ref Dictionary writtenModels, + GenSubset subset, + ExportStreamWriter writer) + { + string exportName = complex.NameForExport(FhirTypeBase.NamingConvention.PascalCase); writtenModels.Add( complex.Name, new WrittenModelInfo() @@ -1055,25 +1087,19 @@ private void WriteResource( IsAbstract = complex.IsAbstract, }); - string filename = Path.Combine(_exportDirectory, "Generated", $"{exportName}.cs"); - _modelWriter.WriteLineIndented($"// {exportName}.cs"); - using (FileStream stream = new FileStream(filename, FileMode.Create)) - using (ExportStreamWriter writer = new ExportStreamWriter(stream)) - { - _writer = writer; + _writer = writer; - WriteHeaderComplexDataType(); + WriteHeaderComplexDataType(); - WriteNamespaceOpen(); + WriteNamespaceOpen(); - WriteComponent(complex, exportName, true, 0, subset); + WriteComponent(complex, exportName, true, 0, subset); - WriteNamespaceClose(); + WriteNamespaceClose(); - WriteFooter(); - } + WriteFooter(); } /// Writes the complex data types. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs index f5ec0fcfd..2b348c976 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs @@ -234,6 +234,13 @@ private enum NullCheckType /// Gets language-specific options and their descriptions. Dictionary ILanguage.LanguageOptions => new Dictionary(); + + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/Cytoscape.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/Cytoscape.cs index 5c76a762e..7472e0648 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/Cytoscape.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/Cytoscape.cs @@ -93,6 +93,13 @@ public sealed class Cytoscape : ILanguage /// Gets language-specific options and their descriptions. Dictionary ILanguage.LanguageOptions => new Dictionary(); + + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/ILanguage.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/ILanguage.cs index be460a2d5..dc8c00001 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/ILanguage.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/ILanguage.cs @@ -3,6 +3,7 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // +using System.IO; using Microsoft.Health.Fhir.SpecManager.Manager; using Microsoft.Health.Fhir.SpecManager.Models; @@ -51,4 +52,9 @@ void Export( FhirCapabiltyStatement serverInfo, ExporterOptions options, string exportDirectory); + + void Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream); } diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/Info.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/Info.cs index e2b986c7b..72c2c169f 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/Info.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/Info.cs @@ -99,6 +99,13 @@ public sealed class Info : ILanguage /// Gets language-specific options and their descriptions. Dictionary ILanguage.LanguageOptions => new(); + + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/LangOpenApiV1.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/LangOpenApiV1.cs index 6e2854c67..594e4e7f8 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/LangOpenApiV1.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/LangOpenApiV1.cs @@ -269,6 +269,12 @@ public sealed class LangOpenApiV1 : ILanguage { "WriteOnly", "If the output should only contain POST/PUT/DELETE operations (false|true)." }, }; + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/LanguageSupportFiles.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/LanguageSupportFiles.cs index a4f3c7a51..ba6454dc2 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/LanguageSupportFiles.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/LanguageSupportFiles.cs @@ -6,6 +6,9 @@ using System.Collections; using System.IO; using static Microsoft.Health.Fhir.SpecManager.Manager.FhirPackageCommon; +#if NETSTANDARD +using Path = Microsoft.Health.Fhir.SpecManager.PathShim; +#endif namespace Microsoft.Health.Fhir.SpecManager.Language; diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/LangOpenApi.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/LangOpenApi.cs index ccf148e7c..1fbebba24 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/LangOpenApi.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/LangOpenApi.cs @@ -64,6 +64,12 @@ public class LangOpenApi : ILanguage /// Gets language-specific options and their descriptions. Dictionary ILanguage.LanguageOptions => OpenApiOptions.LanguageOptions; + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/ModelBuilder.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/ModelBuilder.cs index 451615a18..dea9bd73b 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/ModelBuilder.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/ModelBuilder.cs @@ -13,7 +13,9 @@ using static System.Net.Mime.MediaTypeNames; using static Microsoft.Health.Fhir.CodeGenCommon.Models.FhirCapResource; using static Microsoft.Health.Fhir.SpecManager.Language.OpenApi.OpenApiCommon; +#if !NETSTANDARD using Microsoft.IdentityModel.Protocols.OpenIdConnect; +#endif using System.Threading; using fhirCsR2.Models; @@ -196,6 +198,7 @@ private void AddSmartOAuthScheme(string baseUrl, OpenApiDocument doc, FhirCapSma private async Task getScopes(string endpoint) { +#if !NETSTANDARD try { var retriever = new OpenIdConnectConfigurationRetriever(); @@ -204,6 +207,7 @@ private async Task getScopes(string endpoint) return config.ScopesSupported.ToArray(); } catch +#endif { return Array.Empty(); } diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript.cs index 31ba86e45..aa06f348b 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript.cs @@ -210,6 +210,12 @@ public sealed class TypeScript : ILanguage { "min-ts-version", "Minimum TypeScript version (default: 3.7, use '-' for none)." } }; + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript2.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript2.cs index 9ed5d8228..10f025809 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript2.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript2.cs @@ -215,6 +215,12 @@ private record struct ExportedComplex( { "namespace", "Base namespace for TypeScript classes (default: Fhir.R{VersionNumber})." }, }; + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScriptSdk/TypeScriptSdk.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScriptSdk/TypeScriptSdk.cs index 1555a95d5..648c6ff90 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScriptSdk/TypeScriptSdk.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScriptSdk/TypeScriptSdk.cs @@ -93,6 +93,12 @@ public sealed class TypeScriptSdk : ILanguage { "namespace", "Base namespace for TypeScript classes (default: Fhir.R{VersionNumber})." }, }; + void ILanguage.Export( + FhirVersionInfo info, + FhirComplex complex, + Stream outputStream) + => throw new NotImplementedException(); + /// Export the passed FHIR version into the specified directory. /// The information. /// Information describing the server. @@ -1906,11 +1912,11 @@ private void BuildComplexElementArg( string sdkTypes; if (element.IsArray) { - sdkTypes = string.Join('|', element.ChoiceTypes.Select((ct) => ct.ExportType + "[]")); + sdkTypes = string.Join("|", element.ChoiceTypes.Select((ct) => ct.ExportType + "[]")); } else { - sdkTypes = string.Join('|', element.ChoiceTypes.Select((ct) => ct.ExportType)); + sdkTypes = string.Join("|", element.ChoiceTypes.Select((ct) => ct.ExportType)); } WriteIndentedComment(sb, element.ExportComment); @@ -2086,11 +2092,11 @@ private void BuildComplexElement( { if (isInterface) { - exportType = "(" + string.Join('|', element.ChoiceTypes.Select((ct) => ct.ExportInterfaceType)) + ")"; + exportType = "(" + string.Join("|", element.ChoiceTypes.Select((ct) => ct.ExportInterfaceType)) + ")"; } else { - exportType = "(" + string.Join('|', element.ChoiceTypes.Select((ct) => ct.ExportType)) + ")"; + exportType = "(" + string.Join("|", element.ChoiceTypes.Select((ct) => ct.ExportType)) + ")"; } } else if (isInterface) diff --git a/src/Microsoft.Health.Fhir.SpecManager/Manager/FhirManager.cs b/src/Microsoft.Health.Fhir.SpecManager/Manager/FhirManager.cs index 6915eebe3..44911352d 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Manager/FhirManager.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Manager/FhirManager.cs @@ -356,7 +356,7 @@ public bool TryResolveCanonical( { if (FhirUtils.DefinitionalResourceNames.TryGetValue(components[i], out string resourceName)) { - string part = string.Join('-', components.Where((v, index) => index != i)); + string part = string.Join("-", components.Where((v, index) => index != i)); part = FhirUtils.ToConvention(part, string.Empty, FhirTypeBase.NamingConvention.PascalCase); modified = "http://hl7.org/fhir/" + resourceName + "/" + part; diff --git a/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj b/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj index 113fad88a..1409c4d2b 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj +++ b/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj @@ -1,7 +1,8 @@  - net7.0 + net7.0;netstandard2.0 + 11 2.0.0-beta1 $(PackageVersion) $(PackageVersion) @@ -38,7 +39,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - @@ -56,4 +56,16 @@ + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + diff --git a/src/Microsoft.Health.Fhir.SpecManager/PackageManager/FhirCacheService.cs b/src/Microsoft.Health.Fhir.SpecManager/PackageManager/FhirCacheService.cs index 81a34f40a..9369da281 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/PackageManager/FhirCacheService.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/PackageManager/FhirCacheService.cs @@ -131,7 +131,7 @@ public bool FindOrDownload( if (directive.Contains('#')) { - string[] components = directive.Split('#', StringSplitOptions.TrimEntries); + string[] components = directive.Split('#').Select(x => x.Trim()).ToArray(); name = components[0]; version = components[1]; } @@ -1314,7 +1314,7 @@ private void ProcessSync( return; } - string[] components = directive.Split('#', StringSplitOptions.TrimEntries); + string[] components = directive.Split('#').Select(x => x.Trim()).ToArray(); if (components.Length != 2) { Console.WriteLine($"SynchronizeCache <<< unparseable package directive: {directive}"); diff --git a/src/Microsoft.Health.Fhir.SpecManager/Shim.cs b/src/Microsoft.Health.Fhir.SpecManager/Shim.cs new file mode 100644 index 000000000..deefcb497 --- /dev/null +++ b/src/Microsoft.Health.Fhir.SpecManager/Shim.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; + +namespace Microsoft.Health.Fhir.SpecManager; + +public record struct DateOnly : IComparable +{ + private readonly int _dayNumber; + + public DateOnly(int year, int month, int day) + { + _dayNumber = DayNumberFromDateTime(new DateTime(year, month, day)); + } + + private static int DayNumberFromDateTime(DateTime dt) => (int)((ulong)dt.Ticks / TimeSpan.TicksPerDay); + + public int CompareTo(DateOnly other) => _dayNumber.CompareTo(other._dayNumber); +} + +internal static class Shim +{ + public static bool StartsWith(this string value, char ch) + { + return value.AsSpan()[0] == ch; + } + public static bool EndsWith(this string value, char ch) + { + return value.AsSpan()[^1] == ch; + } + + public static int IndexOf(this string value, char ch, StringComparison stringComparison) + { + return value.IndexOf(ch); + } + + public static bool Contains(this string value, char ch, StringComparison stringComparison) + { + return value.Contains(ch); + } + + public static bool Contains(this string value, string substring, StringComparison stringComparison) + { + return value.Contains(substring); + } + + public static string Replace(this string value, string oldSubstring, string replacement, StringComparison stringComparison) + { + return value.Replace(oldSubstring, replacement); + } + + public static HashSet ToHashSet(this IEnumerable source) + => new HashSet(source); + + public static void Deconstruct(this KeyValuePair pair, out TKey key, out TValue value) + { + key = pair.Key; + value = pair.Value; + } + + public static bool TryAdd(this IDictionary dictionary, TKey key, TValue value) + { + if (!dictionary.ContainsKey(key)) + { + dictionary.Add(key, value); + return true; + } + else + { + return false; + } + } + + public static TSource FirstOrDefault(this IEnumerable source, TSource defaultValue) + { + TSource? first = source.TryGetFirst(out bool found); + return found ? first! : defaultValue; + } + + public static TSource FirstOrDefault(this IEnumerable source, Func predicate, TSource defaultValue) + { + TSource? first = source.TryGetFirst(predicate, out bool found); + return found ? first! : defaultValue; + } + + private static TSource? TryGetFirst(this IEnumerable source, out bool found) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (source is IList list) + { + if (list.Count > 0) + { + found = true; + return list[0]; + } + } + else + { + using (IEnumerator e = source.GetEnumerator()) + { + if (e.MoveNext()) + { + found = true; + return e.Current; + } + } + } + + found = false; + return default; + } + + private static TSource? TryGetFirst(this IEnumerable source, Func predicate, out bool found) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + using (IEnumerator e = source.GetEnumerator()) + { + if (e.MoveNext() && predicate(e.Current)) + { + found = true; + return e.Current; + } + } + + found = false; + return default; + } +} + +public static class PathShim +{ + public static string GetRelativePath(string relativeTo, string path) + { + relativeTo = Path.GetFullPath(relativeTo); + path = Path.GetFullPath(path); + + // Need to check if the roots are different- if they are we need to return the "to" path. + if (Path.GetPathRoot(relativeTo) == Path.GetPathRoot(path)) + return path; + + var index = 0; + var path1Segments = relativeTo.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + var path2Segments = path.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + // if path1 does not end with / it is assumed the end is not a directory + // we will assume that is isn't a directory by ignoring the last split + var len1 = path1Segments.Length - 1; + var len2 = path2Segments.Length; + + // find largest common absolute path between both paths + var min = Math.Min(len1, len2); + while (min > index) + { + if (!string.Equals(path1Segments[index], path2Segments[index])) + { + break; + } + // Handle scenarios where folder and file have same name (only if os supports same name for file and directory) + // e.g. /file/name /file/name/app + else if ((len1 == index && len2 > index + 1) || (len1 > index && len2 == index + 1)) + { + break; + } + ++index; + } + + var result = ""; + + // check if path2 ends with a non-directory separator and if path1 has the same non-directory at the end + if (len1 + 1 == len2 && !string.IsNullOrEmpty(path1Segments[index]) && + string.Equals(path1Segments[index], path2Segments[index])) + { + return result; + } + + for (var i = index; len2 - 1 > i; ++i) + { + result += path2Segments[i] + Path.DirectorySeparatorChar; + } + // if path2 doesn't end with an empty string it means it ended with a non-directory name, so we add it back + if (!string.IsNullOrEmpty(path2Segments[len2 - 1])) + { + result += path2Segments[len2 - 1]; + } + + return result; + } + + public static string Combine(params string[] paths) => Path.Combine(paths); + + public static string GetFileNameWithoutExtension(string path) => Path.GetFileNameWithoutExtension(path); +} diff --git a/src/fhirCsR2/Shim.cs b/src/fhirCsR2/Shim.cs new file mode 100644 index 000000000..38b33708f --- /dev/null +++ b/src/fhirCsR2/Shim.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace fhirCsR2; + +internal static class Shim +{ + public static void Write(this MemoryStream ms, ReadOnlySpan buffer) + { + buffer.CopyTo(new Span(ms.GetBuffer(), (int)ms.Position, buffer.Length)); + } +} diff --git a/src/fhirCsR2/fhirCsR2.csproj b/src/fhirCsR2/fhirCsR2.csproj index cfadb03dd..afe64f373 100644 --- a/src/fhirCsR2/fhirCsR2.csproj +++ b/src/fhirCsR2/fhirCsR2.csproj @@ -1,9 +1,23 @@ - + - net7.0 + net7.0;netstandard2.0 + 11 enable enable + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + From fc1e3f71c84da07547a39c3b9512ee6591bcb0d2 Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Wed, 9 Aug 2023 23:07:36 +0800 Subject: [PATCH 02/15] updates --- SampleSourceGen/Education.StructureDefinition.json | 10 ++++++++++ src/fhirCsR2/Models/DomainResource.cs | 2 +- src/fhirCsR2/fhirCsR2.csproj | 2 -- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/SampleSourceGen/Education.StructureDefinition.json b/SampleSourceGen/Education.StructureDefinition.json index be9469fcd..794ba4f90 100644 --- a/SampleSourceGen/Education.StructureDefinition.json +++ b/SampleSourceGen/Education.StructureDefinition.json @@ -16,6 +16,16 @@ "derivation": "specialization", "snapshot": { "element": [ + { + "id": "Education", + "path": "Education", + "description": "Study or other form of education that a person has done.", + "min": 0, + "max": "*", + "mustSupport": false, + "isModifier": false, + "isSummary": false + }, { "id": "Education.subject", "path": "Education.subject", diff --git a/src/fhirCsR2/Models/DomainResource.cs b/src/fhirCsR2/Models/DomainResource.cs index 5497f725a..4c63759e4 100644 --- a/src/fhirCsR2/Models/DomainResource.cs +++ b/src/fhirCsR2/Models/DomainResource.cs @@ -53,7 +53,7 @@ public class DomainResource : Resource, IFhirJsonSerializable { writer.WritePropertyName("contained"); writer.WriteStartArray(); - foreach (dynamic resource in Contained) + foreach (var resource in Contained) { resource.SerializeJson(writer, options, true); } diff --git a/src/fhirCsR2/fhirCsR2.csproj b/src/fhirCsR2/fhirCsR2.csproj index afe64f373..17f00b526 100644 --- a/src/fhirCsR2/fhirCsR2.csproj +++ b/src/fhirCsR2/fhirCsR2.csproj @@ -8,12 +8,10 @@ - all runtime; build; native; contentfiles; analyzers - From 27660dba77ec9ecc577771d334a050e9c4fb95f7 Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Sat, 12 Aug 2023 07:14:20 +0800 Subject: [PATCH 03/15] Change namespace of generated files to use assembly name and folder structure --- .../Patient.StructureDefinition.json | 0 SampleSourceGen/Program.cs | 14 +++++++ SampleSourceGen/SampleSourceGen.csproj | 3 +- ...Microsoft.Health.Fhir.CodeGenCommon.csproj | 2 +- .../FhirSourceGenerator.cs | 42 +++++++++++++++++-- .../Language/CSharp2.cs | 8 +++- .../Language/CSharpBasic.cs | 8 +++- .../Language/CSharpFirely2.cs | 42 +++++++++++++++---- .../Language/CSharpFirely2IG.cs | 6 +++ .../Language/Cytoscape.cs | 6 +++ .../Language/ILanguage.cs | 2 + .../Language/Info.cs | 6 +++ .../Language/LangOpenApiV1.cs | 6 +++ .../Language/OpenApi/LangOpenApi.cs | 6 +++ .../Language/TypeScript.cs | 6 +++ .../Language/TypeScript2.cs | 6 +++ .../Language/TypeScriptSdk/TypeScriptSdk.cs | 6 +++ .../Microsoft.Health.Fhir.SpecManager.csproj | 2 +- src/fhirCsR2/fhirCsR2.csproj | 2 +- 19 files changed, 154 insertions(+), 19 deletions(-) rename SampleSourceGen/{ => Models}/Patient.StructureDefinition.json (100%) create mode 100644 SampleSourceGen/Program.cs diff --git a/SampleSourceGen/Patient.StructureDefinition.json b/SampleSourceGen/Models/Patient.StructureDefinition.json similarity index 100% rename from SampleSourceGen/Patient.StructureDefinition.json rename to SampleSourceGen/Models/Patient.StructureDefinition.json diff --git a/SampleSourceGen/Program.cs b/SampleSourceGen/Program.cs new file mode 100644 index 000000000..9cdf5492d --- /dev/null +++ b/SampleSourceGen/Program.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using Hl7.Fhir.Model; + +var edu = new SampleSourceGen.Education +{ + Study = "abcd", + Graduated = new FhirBoolean(false), + Subject = new ResourceReference("/Study/abcd") +}; + +var patient = new SampleSourceGen.Models.Patient +{ + Contact = new List { }, +}; diff --git a/SampleSourceGen/SampleSourceGen.csproj b/SampleSourceGen/SampleSourceGen.csproj index 43a7a123a..118878187 100644 --- a/SampleSourceGen/SampleSourceGen.csproj +++ b/SampleSourceGen/SampleSourceGen.csproj @@ -2,12 +2,13 @@ net6.0 + Exe true $(BaseIntermediateOutputPath)\GeneratedFiles - + PreserveNewest diff --git a/src/Microsoft.Health.Fhir.CodeGenCommon/Microsoft.Health.Fhir.CodeGenCommon.csproj b/src/Microsoft.Health.Fhir.CodeGenCommon/Microsoft.Health.Fhir.CodeGenCommon.csproj index 78f7cf49d..8c9f56643 100644 --- a/src/Microsoft.Health.Fhir.CodeGenCommon/Microsoft.Health.Fhir.CodeGenCommon.csproj +++ b/src/Microsoft.Health.Fhir.CodeGenCommon/Microsoft.Health.Fhir.CodeGenCommon.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs index aa3303d51..07bd28b0f 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs @@ -47,13 +47,17 @@ public class FhirSourceGenerator : ISourceGenerator private static readonly DiagnosticDescriptor ProcessSuccess = new( "FHIRGEN005", "Parsing success", - "Canonical: {0}, Artifact Type: {1}, ResourceCount: {2}", + "JsonPath: {0} Canonical: {1}, Artifact Type: {2}, ResourceCount: {3}", "FhirSourceGenerator", - DiagnosticSeverity.Warning, + DiagnosticSeverity.Info, true); public void Execute(GeneratorExecutionContext context) { +#if DEBUG + // System.Diagnostics.Debugger.Launch(); +#endif + try { var fhirConverter = ConverterHelper.ConverterForVersion(FhirPackageCommon.FhirSequenceEnum.R4B); @@ -67,6 +71,8 @@ public void Execute(GeneratorExecutionContext context) continue; } + var namespaceName = context.Compilation.AssemblyName; + var complex = ProcessFile(structureDef.Path, fhirInfo, fhirConverter, out var fileName, out var canonical, out var artifactClass); if (complex == null) { @@ -74,9 +80,12 @@ public void Execute(GeneratorExecutionContext context) continue; } - context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, canonical, artifactClass, fhirInfo.Resources.Count)); + context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, structureDef.Path, canonical, artifactClass, fhirInfo.Resources.Count)); using var memoryStream = new MemoryStream(); + + language.Namespace = GetNamespaceName(namespaceName, structureDef.Path, context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.projectdir", out var projectDir) ? projectDir : null); + language.Export(fhirInfo, complex, memoryStream); memoryStream.Position = 0; @@ -106,6 +115,32 @@ public void Initialize(GeneratorInitializationContext context) { } + private string? GetNamespaceName(string? namespaceName, string path, string? projectPath) + { + string folderName; + if (projectPath != null) + { + folderName = (Path.GetDirectoryName(path) + Path.DirectorySeparatorChar).Replace(projectPath, string.Empty); + if (folderName.EndsWith($"{Path.DirectorySeparatorChar}")) + { + folderName = folderName.Substring(0, folderName.Length - 1); + } + } + else + { + folderName = Path.GetDirectoryName(path).Split(Path.DirectorySeparatorChar).Last(); + } + + if (!string.IsNullOrEmpty(folderName) && folderName != namespaceName) + { + return $"{namespaceName}.{folderName.Replace(Path.DirectorySeparatorChar, '.')}"; + } + else + { + return namespaceName; + } + } + internal FhirComplex? ProcessFile(string path, FhirVersionInfo fhirInfo, IFhirConverter fhirConverter, out string fileName, out string? canonical, out FhirArtifactClassEnum artifactClass) { fileName = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path)); @@ -123,7 +158,6 @@ public void Initialize(GeneratorInitializationContext context) { canonical = null; artifactClass = default; - //context.ReportDiagnostic(Diagnostic.Create(FailedParsingStructureDef, Location.None, path, json)); return null; } diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharp2.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharp2.cs index f26dcb17f..c4eaabf19 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharp2.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharp2.cs @@ -236,6 +236,12 @@ public sealed class CSharp2 : ILanguage /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => _namespace; + set => _namespace = value; + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). @@ -306,7 +312,7 @@ void ILanguage.Export( _exportEnums = false; } - _namespace = options.GetParam("namespace", $"Fhir.{info.FhirSequence}"); + _namespace ??= options.GetParam("namespace", $"Fhir.{info.FhirSequence}"); _namespaceModels = _namespace + ".Models"; _namespaceValueSets = _namespace + ".ValueSets"; _namespaceSerialization = _namespace + ".Serialization"; diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpBasic.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpBasic.cs index 8a545c0bb..9bebc497a 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpBasic.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpBasic.cs @@ -207,6 +207,12 @@ public sealed class CSharpBasic : ILanguage /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => _namespace; + set => _namespace = value; + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). @@ -285,7 +291,7 @@ void ILanguage.Export( switch (key) { case "NAMESPACE": - _namespace = kvp.Value; + _namespace ??= kvp.Value; break; } } diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs index 9943df9fb..a75f5a2aa 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs @@ -15,6 +15,7 @@ public sealed class CSharpFirely2 : ILanguage { /// The namespace to use during export. private const string Namespace = "Hl7.Fhir.Model"; + private string _namespace = Namespace; /// FHIR information we are exporting. private FhirVersionInfo _info; @@ -364,6 +365,12 @@ private enum GenSubset /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => _namespace; + set => _namespace = value; + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). @@ -695,6 +702,11 @@ private void WriteModelInfo( _writer.WriteLineIndented("using System;"); _writer.WriteLineIndented("using System.Collections.Generic;"); _writer.WriteLineIndented("using Hl7.Fhir.Introspection;"); + if (_namespace != Namespace) + { + _writer.WriteLineIndented($"using {Namespace};"); + } + _writer.WriteLineIndented("using Hl7.Fhir.Validation;"); _writer.WriteLineIndented("using System.Linq;"); _writer.WriteLineIndented("using System.Runtime.Serialization;"); @@ -1083,7 +1095,7 @@ private void WriteResource( new WrittenModelInfo() { FhirName = complex.Name, - CsName = $"{Namespace}.{exportName}", + CsName = $"{_namespace}.{exportName}", IsAbstract = complex.IsAbstract, }); @@ -1148,7 +1160,7 @@ private void WriteComplexDataType( new WrittenModelInfo() { FhirName = complex.Name, - CsName = $"{Namespace}.{exportName}", + CsName = $"{_namespace}.{exportName}", IsAbstract = complex.IsAbstract, }); @@ -1224,7 +1236,7 @@ private void WriteComponent( isPatientClass = complex.Name == className; } - if (isPatientClass) interfaces.Add($"{Namespace}.IPatient"); + if (isPatientClass) interfaces.Add($"{_namespace}.IPatient"); var identifierElement = isResource ? complex.Elements.SingleOrDefault(k => isIdentifierProperty(k.Value)).Value : null; if (identifierElement is not null) @@ -2266,9 +2278,11 @@ private WrittenElementInfo BuildElementInfo(string exportedComplexName, FhirElem bool isPrimitive = false; + string ns = Namespace; if (type.Contains('.')) { type = BuildTypeFromPath(type); + ns = _namespace; } string nativeType = type; @@ -2287,7 +2301,7 @@ private WrittenElementInfo BuildElementInfo(string exportedComplexName, FhirElem } else { - nativeType = $"{Namespace}.{type}"; + nativeType = $"{ns}.{type}"; } if (CSharpFirelyCommon.TypeNameMappings.ContainsKey(type)) @@ -2307,8 +2321,8 @@ private WrittenElementInfo BuildElementInfo(string exportedComplexName, FhirElem { FhirElementName = name, PropertyName = isPrimitive ? $"{pascal}Element" : pascal, - PropertyType = isList ? $"List<{Namespace}.{type}>" : $"{Namespace}.{type}", - ElementType = $"{Namespace}.{type}", + PropertyType = isList ? $"List<{ns}.{type}>" : $"{ns}.{type}", + ElementType = $"{ns}.{type}", IsList = isList, IsChoice = element.Name.Contains("[x]", StringComparison.Ordinal), IsPrimitive = isPrimitive, @@ -2820,7 +2834,7 @@ private static string PrimitiveValueInterface(string valueType) /// Writes the namespace open. private void WriteNamespaceOpen() { - _writer.WriteLineIndented($"namespace {Namespace}"); + _writer.WriteLineIndented($"namespace {_namespace}"); OpenScope(); } @@ -2851,6 +2865,11 @@ private void WriteHeaderComplexDataType() _writer.WriteLineIndented("using System.Linq;"); _writer.WriteLineIndented("using System.Runtime.Serialization;"); _writer.WriteLineIndented("using Hl7.Fhir.Introspection;"); + if (_namespace != Namespace) + { + _writer.WriteLineIndented($"using {Namespace};"); + } + _writer.WriteLineIndented("using Hl7.Fhir.Serialization;"); _writer.WriteLineIndented("using Hl7.Fhir.Specification;"); _writer.WriteLineIndented("using Hl7.Fhir.Utility;"); @@ -2874,6 +2893,11 @@ private void WriteHeaderPrimitive() _writer.WriteLineIndented("using System.Runtime.Serialization;"); _writer.WriteLineIndented("using System.Text.RegularExpressions;"); _writer.WriteLineIndented("using Hl7.Fhir.Introspection;"); + if (_namespace != Namespace) + { + _writer.WriteLineIndented($"using {Namespace};"); + } + _writer.WriteLineIndented("using Hl7.Fhir.Specification;"); _writer.WriteLineIndented("using Hl7.Fhir.Validation;"); _writer.WriteLineIndented("using SystemPrimitive = Hl7.Fhir.ElementModel.Types;"); @@ -2974,7 +2998,7 @@ private static void AddModels( } } - private static void AddModels( + private void AddModels( Dictionary total, IEnumerable typesToAdd) { @@ -2989,7 +3013,7 @@ WrittenModelInfo CreateWMI(FhirTypeBase t) return new WrittenModelInfo() { FhirName = t.Name, - CsName = $"{Namespace}.{exportName}", + CsName = $"{_namespace}.{exportName}", IsAbstract = t is FhirComplex c && c.IsAbstract, }; } diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs index 2b348c976..868fbd36a 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs @@ -200,6 +200,12 @@ private enum NullCheckType /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/Cytoscape.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/Cytoscape.cs index 7472e0648..c0b7ce03a 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/Cytoscape.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/Cytoscape.cs @@ -57,6 +57,12 @@ public sealed class Cytoscape : ILanguage /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/ILanguage.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/ILanguage.cs index dc8c00001..b4c13a5b8 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/ILanguage.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/ILanguage.cs @@ -16,6 +16,8 @@ public interface ILanguage /// The name of the language. string LanguageName { get; } + string Namespace { get; set; } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/Info.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/Info.cs index 72c2c169f..4a18a02e1 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/Info.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/Info.cs @@ -63,6 +63,12 @@ public sealed class Info : ILanguage /// The name of the language. string ILanguage.LanguageName => LanguageName; + string ILanguage.Namespace + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/LangOpenApiV1.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/LangOpenApiV1.cs index 594e4e7f8..ae77c8ff7 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/LangOpenApiV1.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/LangOpenApiV1.cs @@ -199,6 +199,12 @@ public sealed class LangOpenApiV1 : ILanguage /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/LangOpenApi.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/LangOpenApi.cs index 1fbebba24..6506d451f 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/LangOpenApi.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/OpenApi/LangOpenApi.cs @@ -27,6 +27,12 @@ public class LangOpenApi : ILanguage /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript.cs index aa06f348b..2a9c1a32c 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript.cs @@ -171,6 +171,12 @@ public sealed class TypeScript : ILanguage /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => _namespace; + set => _namespace = value; + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript2.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript2.cs index 10f025809..ada9fb496 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript2.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScript2.cs @@ -176,6 +176,12 @@ private record struct ExportedComplex( /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScriptSdk/TypeScriptSdk.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScriptSdk/TypeScriptSdk.cs index 648c6ff90..c42f3701d 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScriptSdk/TypeScriptSdk.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/TypeScriptSdk/TypeScriptSdk.cs @@ -53,6 +53,12 @@ public sealed class TypeScriptSdk : ILanguage /// The name of the language. string ILanguage.LanguageName => _languageName; + string ILanguage.Namespace + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } + /// /// Gets the single file extension for this language - null or empty indicates a multi-file /// export (exporter should copy the contents of the directory). diff --git a/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj b/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj index 1409c4d2b..5db2375fe 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj +++ b/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj @@ -62,7 +62,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/src/fhirCsR2/fhirCsR2.csproj b/src/fhirCsR2/fhirCsR2.csproj index 17f00b526..6c2958961 100644 --- a/src/fhirCsR2/fhirCsR2.csproj +++ b/src/fhirCsR2/fhirCsR2.csproj @@ -8,7 +8,7 @@ - + all runtime; build; native; contentfiles; analyzers From 772302bb66d2691a7843782d7a9d75b47c0fd716 Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Wed, 16 Aug 2023 16:08:17 +0800 Subject: [PATCH 04/15] Added sample resource with a custom enum. Removed Microsoft.OpenApi as a dependency for source generation. --- .../Models/Pokemon.StructureDefinition.json | 70 +++++++++ .../Models/PokemonType.CodeSystem.json | 85 +++++++++++ .../Models/PokemonType.ValueSet.json | 18 +++ SampleSourceGen/Program.cs | 7 + SampleSourceGen/SampleSourceGen.csproj | 7 +- TestSourceGen/Program.cs | 2 +- .../FhirSourceGenerator.cs | 143 +++++++++++++----- ...crosoft.Health.Fhir.SourceGenerator.csproj | 8 +- .../Language/CSharpFirely2.cs | 4 +- .../Manager/Differ.cs | 3 - .../Microsoft.Health.Fhir.SpecManager.csproj | 4 +- 11 files changed, 303 insertions(+), 48 deletions(-) create mode 100644 SampleSourceGen/Models/Pokemon.StructureDefinition.json create mode 100644 SampleSourceGen/Models/PokemonType.CodeSystem.json create mode 100644 SampleSourceGen/Models/PokemonType.ValueSet.json diff --git a/SampleSourceGen/Models/Pokemon.StructureDefinition.json b/SampleSourceGen/Models/Pokemon.StructureDefinition.json new file mode 100644 index 000000000..dc4947136 --- /dev/null +++ b/SampleSourceGen/Models/Pokemon.StructureDefinition.json @@ -0,0 +1,70 @@ +{ + "resourceType": "StructureDefinition", + "id": "Pokemon", + "url": "http://hl7.org/fhir/StructureDefinition/Pokemon", + "version": "0.1", + "name": "Pokemon", + "status": "draft", + "fhirVersion": "3.0.1", + "kind": "resource", + "abstract": false, + "type": "Pokemon", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", + "derivation": "specialization", + "snapshot": { + "element": [ + { + "id": "Pokemon.name", + "path": "Pokemon.name", + "min": 1, + "max": "1", + "type": [ + { + "code": "string" + } + ] + }, + { + "id": "Pokemon.nationalDexNo", + "path": "Pokemon.nationalDexNo", + "min": 0, + "max": "1", + "type": [ + { + "code": "integer" + } + ] + }, + { + "id": "Pokemon.primaryType", + "path": "Pokemon.primaryType", + "min": 1, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "binding": { + "strength": "required", + "valueSet": "http://pokemon.com/fhir/ValueSet/pokemontype" + } + }, + { + "id": "Pokemon.secondaryType", + "path": "Pokemon.secondaryType", + "min": 0, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "binding": { + "strength": "required", + "valueSet": "http://pokemon.com/fhir/ValueSet/pokemontype" + } + } + ] + } +} diff --git a/SampleSourceGen/Models/PokemonType.CodeSystem.json b/SampleSourceGen/Models/PokemonType.CodeSystem.json new file mode 100644 index 000000000..4858248c1 --- /dev/null +++ b/SampleSourceGen/Models/PokemonType.CodeSystem.json @@ -0,0 +1,85 @@ +{ + "resourceType": "CodeSystem", + "id": "pokemontypes", + "url": "http://pokemon.com/type", + "version": "1.0.0", + "name": "Pokemon Types", + "title": "Pokemon Types", + "status": "active", + "date": "2023-08-01", + "publisher": "The Pokemon Company", + "concept": [ + { + "code": "normal", + "display": "Normal" + }, + { + "code": "fighting", + "display": "Fighting" + }, + { + "code": "flying", + "display": "Flying" + }, + { + "code": "poison", + "display": "Poison" + }, + { + "code": "ground", + "display": "Ground" + }, + { + "code": "rock", + "display": "Rock" + }, + { + "code": "bug", + "display": "Bug" + }, + { + "code": "ghost", + "display": "Ghost" + }, + { + "code": "steel", + "display": "Steel" + }, + { + "code": "fire", + "display": "Fire" + }, + { + "code": "water", + "display": "Water" + }, + { + "code": "grass", + "display": "Grass" + }, + { + "code": "electric", + "display": "Electric" + }, + { + "code": "psychic", + "display": "Psychic" + }, + { + "code": "ice", + "display": "Ice" + }, + { + "code": "dragon", + "display": "Dragon" + }, + { + "code": "dark", + "display": "Dark" + }, + { + "code": "fairy", + "display": "Fairy" + } + ] +} diff --git a/SampleSourceGen/Models/PokemonType.ValueSet.json b/SampleSourceGen/Models/PokemonType.ValueSet.json new file mode 100644 index 000000000..a8e23695d --- /dev/null +++ b/SampleSourceGen/Models/PokemonType.ValueSet.json @@ -0,0 +1,18 @@ +{ + "resourceType": "ValueSet", + "id": "pokemontype", + "url": "http://pokemon.com/fhir/ValueSet/pokemontype", + "version": "1.0.0", + "name": "Pokemon Types", + "title": "Pokemon Types", + "status": "active", + "date": "2023-08-01", + "publisher": "The Pokemon Company", + "compose": { + "include": [ + { + "system": "http://pokemon.com/type" + } + ] + } +} diff --git a/SampleSourceGen/Program.cs b/SampleSourceGen/Program.cs index 9cdf5492d..005601234 100644 --- a/SampleSourceGen/Program.cs +++ b/SampleSourceGen/Program.cs @@ -12,3 +12,10 @@ { Contact = new List { }, }; + +var pkmn = new SampleSourceGen.Models.Pokemon +{ + Name = "Charmander", + NationalDexNo = 4, + PrimaryType = SampleSourceGen.Models.Pokemon.PokemonTypes.Fire, +}; diff --git a/SampleSourceGen/SampleSourceGen.csproj b/SampleSourceGen/SampleSourceGen.csproj index 118878187..eb3d9680a 100644 --- a/SampleSourceGen/SampleSourceGen.csproj +++ b/SampleSourceGen/SampleSourceGen.csproj @@ -8,13 +8,14 @@ - - PreserveNewest - + + + + diff --git a/TestSourceGen/Program.cs b/TestSourceGen/Program.cs index c7a44b6c9..cebe8663a 100644 --- a/TestSourceGen/Program.cs +++ b/TestSourceGen/Program.cs @@ -13,7 +13,7 @@ var fhirInfo = new FhirVersionInfo(FhirPackageCommon.FhirSequenceEnum.R4B); -var complex = generator.ProcessFile("Patient.StructureDefinition.json", fhirInfo, fhirConverter, out var fileName, out var canonical, out var artifactClass); +var complex = generator.ProcessFile("Patient.StructureDefinition.json", fhirInfo, fhirConverter, m => m.Resources, out var fileName, out var canonical, out var artifactClass); ILanguage language = LanguageHelper.GetLanguages("CSharpFirely2")[0]; using var memoryStream = new MemoryStream(short.MaxValue); diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs index 07bd28b0f..a96105ffb 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs @@ -12,10 +12,12 @@ namespace Microsoft.Health.Fhir.SourceGenerator [Generator] public class FhirSourceGenerator : ISourceGenerator { - private static readonly DiagnosticDescriptor FailedParsingStructureDef = new( + private delegate bool TryGetModel(FhirVersionInfo versionInfo, string key, out TModel model) where TModel : class; + + private static readonly DiagnosticDescriptor FailedArtifactDef = new( "FHIRGEN001", - "Invalid .StructureDefinition.json file", - "Unable to parse StructureDefinition file '{0}'. It must be a valid StructureDefinition file with a snapshot.", + "Invalid artifact file", + "Unable to parse {1} file '{0}'. StructureDefinition files must have a snapshot.", "FhirSourceGenerator", DiagnosticSeverity.Warning, true); @@ -64,42 +66,21 @@ public void Execute(GeneratorExecutionContext context) var fhirInfo = new FhirVersionInfo(FhirPackageCommon.FhirSequenceEnum.R4B); ILanguage language = LanguageHelper.GetLanguages("CSharpFirely2")[0]; - foreach (var structureDef in context.AdditionalFiles.Where(f => f.Path.EndsWith(".StructureDefinition.json", StringComparison.InvariantCultureIgnoreCase))) - { - if (structureDef is null) - { - continue; - } - var namespaceName = context.Compilation.AssemblyName; + ProcessArtifacts(FhirArtifactClassEnum.CodeSystem, context, fhirInfo, fhirConverter, (FhirVersionInfo m, string k, out FhirCodeSystem v) => m.CodeSystems.TryGetValue(k, out v)); + ProcessArtifacts(FhirArtifactClassEnum.ValueSet, context, fhirInfo, fhirConverter, (FhirVersionInfo m, string k, out FhirValueSet v) => m.TryGetValueSet(k, out v)); - var complex = ProcessFile(structureDef.Path, fhirInfo, fhirConverter, out var fileName, out var canonical, out var artifactClass); - if (complex == null) - { - context.ReportDiagnostic(Diagnostic.Create(FailedParsingStructureDef, Location.None, structureDef.Path)); - continue; - } - - context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, structureDef.Path, canonical, artifactClass, fhirInfo.Resources.Count)); - - using var memoryStream = new MemoryStream(); - - language.Namespace = GetNamespaceName(namespaceName, structureDef.Path, context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.projectdir", out var projectDir) ? projectDir : null); - - language.Export(fhirInfo, complex, memoryStream); - memoryStream.Position = 0; - - if (memoryStream.Length == 0) + foreach (var item in fhirInfo.ValueSetsByUrl) + { + var vs = item.Value; + foreach (var v in vs.ValueSetsByVersion) { - context.ReportDiagnostic(Diagnostic.Create(FailedToGenerate, Location.None, structureDef.Path)); - continue; + v.Value.Resolve(fhirInfo.CodeSystems); } - - var code = Encoding.UTF8.GetString(memoryStream.ToArray()); - - context.AddSource($"{fileName}.gen.cs", SourceText.From(code, Encoding.UTF8)); } + ProcessStructureDefinitions(context, fhirInfo, fhirConverter, language); + } catch (ReflectionTypeLoadException rex) { @@ -115,6 +96,78 @@ public void Initialize(GeneratorInitializationContext context) { } + private List ProcessArtifacts( + FhirArtifactClassEnum expectedArtifactClass, + GeneratorExecutionContext context, + FhirVersionInfo fhirInfo, + IFhirConverter fhirConverter, + TryGetModel modelCollectionLocator) + where TModel : class + { + var result = new List(); + foreach (var valueSet in context.AdditionalFiles.Where(f => f.Path.EndsWith($".{expectedArtifactClass}.json", StringComparison.InvariantCultureIgnoreCase))) + { + if (valueSet is null) + { + continue; + } + + var namespaceName = context.Compilation.AssemblyName; + + var model = ProcessFile(valueSet.Path, fhirInfo, fhirConverter, modelCollectionLocator, out var fileName, out var canonical, out var artifactClass); + if (model == null || artifactClass != expectedArtifactClass) + { + context.ReportDiagnostic(Diagnostic.Create(FailedArtifactDef, Location.None, valueSet.Path, expectedArtifactClass)); + continue; + } + + result.Add(model); + + context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, valueSet.Path, canonical, artifactClass, fhirInfo.Resources.Count)); + } + + return result; + } + + private void ProcessStructureDefinitions(GeneratorExecutionContext context, FhirVersionInfo fhirInfo, IFhirConverter fhirConverter, ILanguage language) + { + foreach (var structureDef in context.AdditionalFiles.Where(f => f.Path.EndsWith(".StructureDefinition.json", StringComparison.InvariantCultureIgnoreCase))) + { + if (structureDef is null) + { + continue; + } + + var namespaceName = context.Compilation.AssemblyName; + + var complex = ProcessFile(structureDef.Path, fhirInfo, fhirConverter, m => m.Resources, out var fileName, out var canonical, out var artifactClass); + if (complex == null && artifactClass != FhirArtifactClassEnum.Resource) + { + context.ReportDiagnostic(Diagnostic.Create(FailedArtifactDef, Location.None, structureDef.Path, FhirArtifactClassEnum.Resource)); + continue; + } + + context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, structureDef.Path, canonical, artifactClass, fhirInfo.Resources.Count)); + + using var memoryStream = new MemoryStream(); + + language.Namespace = GetNamespaceName(namespaceName, structureDef.Path, context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.projectdir", out var projectDir) ? projectDir : null); + + language.Export(fhirInfo, complex, memoryStream); + memoryStream.Position = 0; + + if (memoryStream.Length == 0) + { + context.ReportDiagnostic(Diagnostic.Create(FailedToGenerate, Location.None, structureDef.Path)); + continue; + } + + var code = Encoding.UTF8.GetString(memoryStream.ToArray()); + + context.AddSource($"{fileName}.gen.cs", SourceText.From(code, Encoding.UTF8)); + } + } + private string? GetNamespaceName(string? namespaceName, string path, string? projectPath) { string folderName; @@ -141,7 +194,25 @@ public void Initialize(GeneratorInitializationContext context) } } - internal FhirComplex? ProcessFile(string path, FhirVersionInfo fhirInfo, IFhirConverter fhirConverter, out string fileName, out string? canonical, out FhirArtifactClassEnum artifactClass) + internal TModel? ProcessFile( + string path, + FhirVersionInfo fhirInfo, + IFhirConverter fhirConverter, + Func> modelCollectionAccessor, out string fileName, + out string? canonical, + out FhirArtifactClassEnum artifactClass) + where TModel : class + => ProcessFile(path, fhirInfo, fhirConverter, (FhirVersionInfo m, string k, out TModel v) => modelCollectionAccessor(m).TryGetValue(k, out v), out fileName, out canonical, out artifactClass); + + private TModel? ProcessFile( + string path, + FhirVersionInfo fhirInfo, + IFhirConverter fhirConverter, + TryGetModel modelCollectionLocator, + out string fileName, + out string? canonical, + out FhirArtifactClassEnum artifactClass) + where TModel : class { fileName = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path)); @@ -163,8 +234,8 @@ public void Initialize(GeneratorInitializationContext context) fhirInfo.ProcessResource(resource, out canonical, out artifactClass); - fhirInfo.Resources.TryGetValue(fileName, out var complex); - return complex; + modelCollectionLocator(fhirInfo, fileName, out var model); + return model; } } } diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj b/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj index f6972495d..95a5fa2e6 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj @@ -24,13 +24,18 @@ - + + + + + + @@ -44,7 +49,6 @@ - diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs index a75f5a2aa..4bd775d7d 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2.cs @@ -2037,8 +2037,8 @@ private WrittenElementInfo BuildCodedElementInfo(FhirElement element) } else { - codeLiteral = $"Code<{Namespace}.{vsClass}.{vsName}>"; - enumClass = $"{Namespace}.{vsClass}.{vsName}"; + codeLiteral = $"Code<{_namespace}.{vsClass}.{vsName}>"; + enumClass = $"{_namespace}.{vsClass}.{vsName}"; if (vsName.ToUpperInvariant() == pascal.ToUpperInvariant()) { diff --git a/src/Microsoft.Health.Fhir.SpecManager/Manager/Differ.cs b/src/Microsoft.Health.Fhir.SpecManager/Manager/Differ.cs index 2cee0f9a2..f9f73e48c 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Manager/Differ.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Manager/Differ.cs @@ -3,9 +3,6 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // -using System.Globalization; -using Microsoft.OpenApi.Any; - namespace Microsoft.Health.Fhir.SpecManager.Manager; /// Class that performs a diff between two FhirVersionInfo packages. diff --git a/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj b/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj index 5db2375fe..ff6b84adf 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj +++ b/src/Microsoft.Health.Fhir.SpecManager/Microsoft.Health.Fhir.SpecManager.csproj @@ -39,7 +39,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - @@ -57,11 +56,14 @@ + + + all runtime; build; native; contentfiles; analyzers From 3c927b4cad4c35a404bc2f51f6619744d2259b28 Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Wed, 16 Aug 2023 23:37:45 +0800 Subject: [PATCH 05/15] Restore codegenerated regex for net7 --- .../Models/FhirUtils.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirUtils.cs b/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirUtils.cs index cce85b986..c2326923a 100644 --- a/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirUtils.cs +++ b/src/Microsoft.Health.Fhir.CodeGenCommon/Models/FhirUtils.cs @@ -650,9 +650,20 @@ public static string SanitizeForProperty( return value; } - private static Regex RegexRemoveDuplicateLines() => new Regex("__+", RegexOptions.Compiled); +#if NET7_0_OR_GREATER + [GeneratedRegex("__+")] + private static partial Regex RegexRemoveDuplicateLines(); - private static Regex RegexRemoveDuplicateWhitespace() => new Regex("\\s+", RegexOptions.Compiled); + [GeneratedRegex("\\s+")] + private static partial Regex RegexRemoveDuplicateWhitespace(); - private static Regex RegexAsciiEscapingR() => new Regex("[^ -~]+", RegexOptions.Compiled); + [GeneratedRegex("[^ -~]+")] + private static partial Regex RegexAsciiEscapingR(); +#else + private static Regex RegexRemoveDuplicateLines() => new("__+", RegexOptions.Compiled); + + private static Regex RegexRemoveDuplicateWhitespace() => new("\\s+", RegexOptions.Compiled); + + private static Regex RegexAsciiEscapingR() => new("[^ -~]+", RegexOptions.Compiled); +#endif } From 879db434da428dc9ce556d58913d9ebdd1fc0c7e Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Thu, 17 Aug 2023 00:37:14 +0800 Subject: [PATCH 06/15] Improve json processing --- .../FhirSourceGenerator.cs | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs index a96105ffb..a17c6d8e8 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs @@ -6,6 +6,7 @@ using Microsoft.Health.Fhir.SpecManager.Converters; using Microsoft.Health.Fhir.SpecManager.Language; using Microsoft.Health.Fhir.SpecManager.Manager; +using Microsoft.Health.Fhir.SpecManager.Models; namespace Microsoft.Health.Fhir.SourceGenerator { @@ -54,21 +55,21 @@ public class FhirSourceGenerator : ISourceGenerator DiagnosticSeverity.Info, true); + private static readonly ILanguage language = new CSharpFirely2(); + private static readonly IFhirConverter fhirConverter = new FromFhirExpando(); + public void Execute(GeneratorExecutionContext context) { #if DEBUG - // System.Diagnostics.Debugger.Launch(); + System.Diagnostics.Debugger.Launch(); #endif try { - var fhirConverter = ConverterHelper.ConverterForVersion(FhirPackageCommon.FhirSequenceEnum.R4B); - var fhirInfo = new FhirVersionInfo(FhirPackageCommon.FhirSequenceEnum.R4B); - ILanguage language = LanguageHelper.GetLanguages("CSharpFirely2")[0]; - ProcessArtifacts(FhirArtifactClassEnum.CodeSystem, context, fhirInfo, fhirConverter, (FhirVersionInfo m, string k, out FhirCodeSystem v) => m.CodeSystems.TryGetValue(k, out v)); - ProcessArtifacts(FhirArtifactClassEnum.ValueSet, context, fhirInfo, fhirConverter, (FhirVersionInfo m, string k, out FhirValueSet v) => m.TryGetValueSet(k, out v)); + ProcessArtifacts(FhirArtifactClassEnum.CodeSystem, context, fhirInfo, (FhirVersionInfo m, string k, out FhirCodeSystem v) => m.CodeSystems.TryGetValue(k, out v)); + ProcessArtifacts(FhirArtifactClassEnum.ValueSet, context, fhirInfo, (FhirVersionInfo m, string k, out FhirValueSet v) => m.TryGetValueSet(k, out v)); foreach (var item in fhirInfo.ValueSetsByUrl) { @@ -79,7 +80,7 @@ public void Execute(GeneratorExecutionContext context) } } - ProcessStructureDefinitions(context, fhirInfo, fhirConverter, language); + ProcessStructureDefinitions(context, fhirInfo); } catch (ReflectionTypeLoadException rex) @@ -96,15 +97,13 @@ public void Initialize(GeneratorInitializationContext context) { } - private List ProcessArtifacts( + private void ProcessArtifacts( FhirArtifactClassEnum expectedArtifactClass, GeneratorExecutionContext context, FhirVersionInfo fhirInfo, - IFhirConverter fhirConverter, TryGetModel modelCollectionLocator) where TModel : class { - var result = new List(); foreach (var valueSet in context.AdditionalFiles.Where(f => f.Path.EndsWith($".{expectedArtifactClass}.json", StringComparison.InvariantCultureIgnoreCase))) { if (valueSet is null) @@ -114,22 +113,18 @@ private List ProcessArtifacts( var namespaceName = context.Compilation.AssemblyName; - var model = ProcessFile(valueSet.Path, fhirInfo, fhirConverter, modelCollectionLocator, out var fileName, out var canonical, out var artifactClass); + var model = ProcessFile(valueSet.Path, fhirInfo, fhirConverter, modelCollectionLocator, out var fileName, out var canonical, out var artifactClass); if (model == null || artifactClass != expectedArtifactClass) { context.ReportDiagnostic(Diagnostic.Create(FailedArtifactDef, Location.None, valueSet.Path, expectedArtifactClass)); continue; } - result.Add(model); - context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, valueSet.Path, canonical, artifactClass, fhirInfo.Resources.Count)); } - - return result; } - private void ProcessStructureDefinitions(GeneratorExecutionContext context, FhirVersionInfo fhirInfo, IFhirConverter fhirConverter, ILanguage language) + private void ProcessStructureDefinitions(GeneratorExecutionContext context, FhirVersionInfo fhirInfo) { foreach (var structureDef in context.AdditionalFiles.Where(f => f.Path.EndsWith(".StructureDefinition.json", StringComparison.InvariantCultureIgnoreCase))) { @@ -140,7 +135,7 @@ private void ProcessStructureDefinitions(GeneratorExecutionContext context, Fhir var namespaceName = context.Compilation.AssemblyName; - var complex = ProcessFile(structureDef.Path, fhirInfo, fhirConverter, m => m.Resources, out var fileName, out var canonical, out var artifactClass); + var complex = ProcessFile(structureDef.Path, fhirInfo, fhirConverter, m => m.Resources, out var id, out var canonical, out var artifactClass); if (complex == null && artifactClass != FhirArtifactClassEnum.Resource) { context.ReportDiagnostic(Diagnostic.Create(FailedArtifactDef, Location.None, structureDef.Path, FhirArtifactClassEnum.Resource)); @@ -164,7 +159,7 @@ private void ProcessStructureDefinitions(GeneratorExecutionContext context, Fhir var code = Encoding.UTF8.GetString(memoryStream.ToArray()); - context.AddSource($"{fileName}.gen.cs", SourceText.From(code, Encoding.UTF8)); + context.AddSource($"{id}.cs", SourceText.From(code, Encoding.UTF8)); } } @@ -202,19 +197,19 @@ private void ProcessStructureDefinitions(GeneratorExecutionContext context, Fhir out string? canonical, out FhirArtifactClassEnum artifactClass) where TModel : class - => ProcessFile(path, fhirInfo, fhirConverter, (FhirVersionInfo m, string k, out TModel v) => modelCollectionAccessor(m).TryGetValue(k, out v), out fileName, out canonical, out artifactClass); + => ProcessFile(path, fhirInfo, fhirConverter, (FhirVersionInfo m, string k, out TModel v) => modelCollectionAccessor(m).TryGetValue(k, out v), out fileName, out canonical, out artifactClass); private TModel? ProcessFile( string path, FhirVersionInfo fhirInfo, IFhirConverter fhirConverter, TryGetModel modelCollectionLocator, - out string fileName, + out string id, out string? canonical, out FhirArtifactClassEnum artifactClass) where TModel : class { - fileName = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path)); + id = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path)); if (!File.Exists(path)) { @@ -225,16 +220,32 @@ private void ProcessStructureDefinitions(GeneratorExecutionContext context, Fhir var json = File.ReadAllText(path); - if (!fhirConverter.TryParseResource(json, out var resource, out var resourceType)) + if (!fhirConverter.TryParseResource(json, out var resource, out _)) { canonical = null; artifactClass = default; return null; } + if (resource is FhirExpando expando) + { + if (expando.TryGetValue("type", out var typeVal) && typeVal is string typeName) + { + id = typeName; + } + else if(expando.TryGetValue("url", out var urlVal) && urlVal is string url) + { + id = url; + } + else if (expando.TryGetValue("id", out var idVal) && urlVal is string id2) + { + id = id2; + } + } + fhirInfo.ProcessResource(resource, out canonical, out artifactClass); - modelCollectionLocator(fhirInfo, fileName, out var model); + modelCollectionLocator(fhirInfo, id, out var model); return model; } } From 4dd23ecb59e04d62be345e06f42d2babcc403260 Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Thu, 17 Aug 2023 10:43:46 +0800 Subject: [PATCH 07/15] Improve code structure --- .../FhirSourceGenerator.cs | 41 ++++++++++--------- ...crosoft.Health.Fhir.SourceGenerator.csproj | 2 +- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs index a17c6d8e8..8a1a76eec 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs @@ -61,7 +61,7 @@ public class FhirSourceGenerator : ISourceGenerator public void Execute(GeneratorExecutionContext context) { #if DEBUG - System.Diagnostics.Debugger.Launch(); + // System.Diagnostics.Debugger.Launch(); #endif try @@ -89,7 +89,7 @@ public void Execute(GeneratorExecutionContext context) } catch (Exception ex) { - context.ReportDiagnostic(Diagnostic.Create(UnhandledException, Location.None, ex.StackTrace.Replace(Environment.NewLine, ""))); + context.ReportDiagnostic(Diagnostic.Create(UnhandledException, Location.None, ex)); } } @@ -133,10 +133,8 @@ private void ProcessStructureDefinitions(GeneratorExecutionContext context, Fhir continue; } - var namespaceName = context.Compilation.AssemblyName; - var complex = ProcessFile(structureDef.Path, fhirInfo, fhirConverter, m => m.Resources, out var id, out var canonical, out var artifactClass); - if (complex == null && artifactClass != FhirArtifactClassEnum.Resource) + if (complex == null || artifactClass != FhirArtifactClassEnum.Resource) { context.ReportDiagnostic(Diagnostic.Create(FailedArtifactDef, Location.None, structureDef.Path, FhirArtifactClassEnum.Resource)); continue; @@ -144,23 +142,27 @@ private void ProcessStructureDefinitions(GeneratorExecutionContext context, Fhir context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, structureDef.Path, canonical, artifactClass, fhirInfo.Resources.Count)); - using var memoryStream = new MemoryStream(); - - language.Namespace = GetNamespaceName(namespaceName, structureDef.Path, context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.projectdir", out var projectDir) ? projectDir : null); + AddFhirResourceSource(context, fhirInfo, complex, structureDef.Path); + } + } - language.Export(fhirInfo, complex, memoryStream); - memoryStream.Position = 0; + private void AddFhirResourceSource(GeneratorExecutionContext context, FhirVersionInfo fhirInfo, FhirComplex complex, string originalFilePath) + { + var namespaceName = context.Compilation.AssemblyName; + language.Namespace = GetNamespaceName(namespaceName, originalFilePath, context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.projectdir", out var projectDir) ? projectDir : null); + using var memoryStream = new MemoryStream(); + language.Export(fhirInfo, complex, memoryStream); + memoryStream.Position = 0; - if (memoryStream.Length == 0) - { - context.ReportDiagnostic(Diagnostic.Create(FailedToGenerate, Location.None, structureDef.Path)); - continue; - } + if (memoryStream.Length == 0) + { + context.ReportDiagnostic(Diagnostic.Create(FailedToGenerate, Location.None, originalFilePath)); + return; + } - var code = Encoding.UTF8.GetString(memoryStream.ToArray()); + var code = Encoding.UTF8.GetString(memoryStream.ToArray()); - context.AddSource($"{id}.cs", SourceText.From(code, Encoding.UTF8)); - } + context.AddSource($"{complex.Id}.cs", SourceText.From(code, Encoding.UTF8)); } private string? GetNamespaceName(string? namespaceName, string path, string? projectPath) @@ -193,7 +195,8 @@ private void ProcessStructureDefinitions(GeneratorExecutionContext context, Fhir string path, FhirVersionInfo fhirInfo, IFhirConverter fhirConverter, - Func> modelCollectionAccessor, out string fileName, + Func> modelCollectionAccessor, + out string fileName, out string? canonical, out FhirArtifactClassEnum artifactClass) where TModel : class diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj b/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj index 95a5fa2e6..d62433869 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj @@ -48,7 +48,7 @@ - + From d620ed8929faa1b1fcc68286ef6e28e22e048e1e Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Thu, 17 Aug 2023 10:53:16 +0800 Subject: [PATCH 08/15] Remove testing configuration --- SampleSourceGen/SampleSourceGen.csproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/SampleSourceGen/SampleSourceGen.csproj b/SampleSourceGen/SampleSourceGen.csproj index eb3d9680a..dce58285d 100644 --- a/SampleSourceGen/SampleSourceGen.csproj +++ b/SampleSourceGen/SampleSourceGen.csproj @@ -3,8 +3,6 @@ net6.0 Exe - true - $(BaseIntermediateOutputPath)\GeneratedFiles From 88836ee66cc0bec7f94f2965515d2931c67c2678 Mon Sep 17 00:00:00 2001 From: almostchristian Date: Mon, 16 Oct 2023 14:20:27 +0800 Subject: [PATCH 09/15] Refactored code generation to use custom attribute for generation. Definition files are no longer required to be added as AdditionalFiles --- SampleSourceGen/Education.cs | 8 + SampleSourceGen/Models/Patient.cs | 8 + .../Models/Pokemon.StructureDefinition.json | 2 +- SampleSourceGen/Models/Pokemon.cs | 10 + .../Models/PokemonType.CodeSystem.json | 1 + SampleSourceGen/SampleSourceGen.csproj | 4 +- TestSourceGen/Program.cs | 22 +- fhir-codegen.sln | 9 +- src/Directory.Build.props | 41 +++ .../GeneratedFhirAttribute.cs | 25 ++ ...icrosoft.Health.Fhir.CodeGeneration.csproj | 53 ++++ .../DiagnosticDescriptors.cs | 46 ++++ .../Emitter.cs | 195 ++++++++++++++ .../FhirSourceGenerator.cs | 246 ++---------------- ...crosoft.Health.Fhir.SourceGenerator.csproj | 27 +- .../Parsing/Helpers.cs | 129 +++++++++ .../Parsing/Parser.cs | 207 +++++++++++++++ .../Parsing/ResourcePartialClass.cs | 3 + .../Parsing/SymbolVisibility.cs | 8 + .../Parsing/SyntaxContextReceiver.cs | 57 ++++ 20 files changed, 829 insertions(+), 272 deletions(-) create mode 100644 SampleSourceGen/Education.cs create mode 100644 SampleSourceGen/Models/Patient.cs create mode 100644 SampleSourceGen/Models/Pokemon.cs create mode 100644 src/Directory.Build.props create mode 100644 src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs create mode 100644 src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj create mode 100644 src/Microsoft.Health.Fhir.SourceGenerator/DiagnosticDescriptors.cs create mode 100644 src/Microsoft.Health.Fhir.SourceGenerator/Emitter.cs create mode 100644 src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Helpers.cs create mode 100644 src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs create mode 100644 src/Microsoft.Health.Fhir.SourceGenerator/Parsing/ResourcePartialClass.cs create mode 100644 src/Microsoft.Health.Fhir.SourceGenerator/Parsing/SymbolVisibility.cs create mode 100644 src/Microsoft.Health.Fhir.SourceGenerator/Parsing/SyntaxContextReceiver.cs diff --git a/SampleSourceGen/Education.cs b/SampleSourceGen/Education.cs new file mode 100644 index 000000000..bdd540b4b --- /dev/null +++ b/SampleSourceGen/Education.cs @@ -0,0 +1,8 @@ +using Microsoft.Health.Fhir.CodeGeneration; + +namespace SampleSourceGen; + +[GeneratedFhir("Education.StructureDefinition.json")] +public partial class Education +{ +} diff --git a/SampleSourceGen/Models/Patient.cs b/SampleSourceGen/Models/Patient.cs new file mode 100644 index 000000000..046a4f35a --- /dev/null +++ b/SampleSourceGen/Models/Patient.cs @@ -0,0 +1,8 @@ +using Microsoft.Health.Fhir.CodeGeneration; + +namespace SampleSourceGen.Models; + +[GeneratedFhir("Models/Patient.StructureDefinition.json")] +public partial class Patient +{ +} diff --git a/SampleSourceGen/Models/Pokemon.StructureDefinition.json b/SampleSourceGen/Models/Pokemon.StructureDefinition.json index dc4947136..1d7d771fc 100644 --- a/SampleSourceGen/Models/Pokemon.StructureDefinition.json +++ b/SampleSourceGen/Models/Pokemon.StructureDefinition.json @@ -5,7 +5,7 @@ "version": "0.1", "name": "Pokemon", "status": "draft", - "fhirVersion": "3.0.1", + "fhirVersion": "4.3.0", "kind": "resource", "abstract": false, "type": "Pokemon", diff --git a/SampleSourceGen/Models/Pokemon.cs b/SampleSourceGen/Models/Pokemon.cs new file mode 100644 index 000000000..daca67379 --- /dev/null +++ b/SampleSourceGen/Models/Pokemon.cs @@ -0,0 +1,10 @@ +using Microsoft.Health.Fhir.CodeGeneration; + +namespace SampleSourceGen.Models; + +[GeneratedFhir( + "Models/Pokemon.StructureDefinition.json", + TerminologyResources = new[] { "Models/PokemonType.CodeSystem.json", "Models/PokemonType.ValueSet.json" })] +public partial class Pokemon +{ +} diff --git a/SampleSourceGen/Models/PokemonType.CodeSystem.json b/SampleSourceGen/Models/PokemonType.CodeSystem.json index 4858248c1..399ea6890 100644 --- a/SampleSourceGen/Models/PokemonType.CodeSystem.json +++ b/SampleSourceGen/Models/PokemonType.CodeSystem.json @@ -8,6 +8,7 @@ "status": "active", "date": "2023-08-01", "publisher": "The Pokemon Company", + "content": "complete", "concept": [ { "code": "normal", diff --git a/SampleSourceGen/SampleSourceGen.csproj b/SampleSourceGen/SampleSourceGen.csproj index dce58285d..4ddfaa4e1 100644 --- a/SampleSourceGen/SampleSourceGen.csproj +++ b/SampleSourceGen/SampleSourceGen.csproj @@ -3,6 +3,8 @@ net6.0 Exe + true + $(BaseIntermediateOutputPath)\GeneratedFiles @@ -17,7 +19,7 @@ - + diff --git a/TestSourceGen/Program.cs b/TestSourceGen/Program.cs index cebe8663a..608705a3e 100644 --- a/TestSourceGen/Program.cs +++ b/TestSourceGen/Program.cs @@ -1,26 +1,12 @@ // See https://aka.ms/new-console-template for more information -using System.Text; -using Microsoft.CodeAnalysis; using Microsoft.Health.Fhir.SourceGenerator; -using Microsoft.Health.Fhir.SpecManager.Converters; -using Microsoft.Health.Fhir.SpecManager.Language; -using Microsoft.Health.Fhir.SpecManager.Manager; +using Microsoft.Health.Fhir.SourceGenerator.Parsing; -var generator = new FhirSourceGenerator(); +var resourceClass = new ResourcePartialClass(typeof(Program).Namespace!, "Patient", "Patient.StructureDefinition.json", Array.Empty()); -var fhirConverter = ConverterHelper.ConverterForVersion(FhirPackageCommon.FhirSequenceEnum.R4B); +var emitter = new Emitter(resourceClass, diag => Console.Error.WriteLine(diag.GetMessage())); -var fhirInfo = new FhirVersionInfo(FhirPackageCommon.FhirSequenceEnum.R4B); - -var complex = generator.ProcessFile("Patient.StructureDefinition.json", fhirInfo, fhirConverter, m => m.Resources, out var fileName, out var canonical, out var artifactClass); - -ILanguage language = LanguageHelper.GetLanguages("CSharpFirely2")[0]; -using var memoryStream = new MemoryStream(short.MaxValue); -language.Export(fhirInfo, complex, memoryStream); - -memoryStream.Seek(0, SeekOrigin.Begin); -StreamReader reader = new StreamReader(memoryStream, Encoding.UTF8); -var code = await reader.ReadToEndAsync(); +var code = emitter.Emit(); Console.WriteLine(code); diff --git a/fhir-codegen.sln b/fhir-codegen.sln index 73040eb00..bdd90a34e 100644 --- a/fhir-codegen.sln +++ b/fhir-codegen.sln @@ -8,6 +8,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig .gitignore = .gitignore CODE_OF_CONDUCT.md = CODE_OF_CONDUCT.md + src\Directory.Build.props = src\Directory.Build.props .github\workflows\docs.yaml = .github\workflows\docs.yaml GeoPol.xml = GeoPol.xml LICENSE = LICENSE @@ -36,7 +37,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleSourceGen", "SampleSo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Fhir.SourceGenerator", "src\Microsoft.Health.Fhir.SourceGenerator\Microsoft.Health.Fhir.SourceGenerator.csproj", "{213EE0DD-ECE8-47AF-8301-42BEAE4EFE54}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestSourceGen", "TestSourceGen\TestSourceGen.csproj", "{956E4954-BBC8-4471-B53C-9424F1FE681A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestSourceGen", "TestSourceGen\TestSourceGen.csproj", "{956E4954-BBC8-4471-B53C-9424F1FE681A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Health.Fhir.CodeGeneration", "src\Microsoft.Health.Fhir.CodeGeneration\Microsoft.Health.Fhir.CodeGeneration.csproj", "{37BFB554-48B3-4BBA-83ED-415956898C48}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -80,6 +83,10 @@ Global {956E4954-BBC8-4471-B53C-9424F1FE681A}.Debug|Any CPU.Build.0 = Debug|Any CPU {956E4954-BBC8-4471-B53C-9424F1FE681A}.Release|Any CPU.ActiveCfg = Release|Any CPU {956E4954-BBC8-4471-B53C-9424F1FE681A}.Release|Any CPU.Build.0 = Release|Any CPU + {37BFB554-48B3-4BBA-83ED-415956898C48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {37BFB554-48B3-4BBA-83ED-415956898C48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {37BFB554-48B3-4BBA-83ED-415956898C48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {37BFB554-48B3-4BBA-83ED-415956898C48}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 000000000..f8770533e --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,41 @@ + + + + + + + + + + + <_TargetPathsToSymbols Include="@(_AnalyzerFile)" TargetPath="/%(_AnalyzerFile.PackagePath)" Condition="%(_AnalyzerFile.IsSymbol)" /> + + + + + + <_analyzerPath>analyzers/dotnet/cs + <_analyzerPath Condition="'$(AnalyzerRoslynVersion)' != ''">$(_analyzerPath)/roslyn$(AnalyzerRoslynVersion) + <_analyzerPath Condition="'$(AnalyzerLanguage)' != ''">$(_analyzerPath)/$(AnalyzerLanguage) + + + + + <_AnalyzerPackFile Include="@(_BuildOutputInPackage->WithMetadataValue('TargetFramework', 'netstandard2.0'))" IsSymbol="false" /> + <_AnalyzerPackFile Include="@(_TargetPathsToSymbols->WithMetadataValue('TargetFramework', 'netstandard2.0'))" IsSymbol="true" /> + <_AnalyzerPackFile PackagePath="$(_analyzerPath)/%(TargetPath)" /> + + + + + + diff --git a/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs b/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs new file mode 100644 index 000000000..fb2f6e03a --- /dev/null +++ b/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs @@ -0,0 +1,25 @@ +using System; + +namespace Microsoft.Health.Fhir.CodeGeneration; + +[AttributeUsage(AttributeTargets.Class)] +public class GeneratedFhirAttribute : Attribute +{ + /// + /// Initializes a new instance of the class. + /// + public GeneratedFhirAttribute(string structureDefinitionPath) + { + StructureDefinitionPath = structureDefinitionPath; + } + + /// + /// The relative path to the structure definition resource json file. + /// + public string StructureDefinitionPath { get; } + + /// + /// The relative paths to the terminology resource (CodeSystem/ValueSet) json files. + /// + public string[] TerminologyResources { get; set; } = Array.Empty(); +} diff --git a/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj new file mode 100644 index 000000000..20c631bab --- /dev/null +++ b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj @@ -0,0 +1,53 @@ + + + + netstandard2.0 + 10.0 + true + true + true + analyzers\cs + 0.1.0-beta.2 + + + + true + $(BeforePack);IncludeAnalyzersInPackage; + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/DiagnosticDescriptors.cs b/src/Microsoft.Health.Fhir.SourceGenerator/DiagnosticDescriptors.cs new file mode 100644 index 000000000..b591c5195 --- /dev/null +++ b/src/Microsoft.Health.Fhir.SourceGenerator/DiagnosticDescriptors.cs @@ -0,0 +1,46 @@ +using Microsoft.CodeAnalysis; + +namespace Microsoft.Health.Fhir.SourceGenerator; + +internal static class DiagnosticDescriptors +{ + public static readonly DiagnosticDescriptor FailedArtifactDef = new( + "FHIRGEN001", + "Invalid artifact file", + "Unable to parse {1} file '{0}'. StructureDefinition files must have a snapshot.", + "FhirSourceGenerator", + DiagnosticSeverity.Warning, + true); + + public static readonly DiagnosticDescriptor TypeLoaderException = new( + "FHIRGEN002", + "Fatal FhirCode Generation error", + "Type loader exception '{0}'.", + "FhirSourceGenerator", + DiagnosticSeverity.Error, + true); + + public static readonly DiagnosticDescriptor UnhandledException = new( + "FHIRGEN003", + "Fatal FhirCode Generation error", + "Unhandled exception '{0}'.", + "FhirSourceGenerator", + DiagnosticSeverity.Error, + true); + + public static readonly DiagnosticDescriptor FailedToGenerate = new( + "FHIRGEN004", + "Invalid .StructureDefinition.json file", + "Failed to generate code for json file [{0}]{1}.", + "FhirSourceGenerator", + DiagnosticSeverity.Error, + true); + + public static readonly DiagnosticDescriptor ProcessSuccess = new( + "FHIRGEN005", + "Parsing success", + "JsonPath: {0} Canonical: {1}, Artifact Type: {2}, ResourceCount: {3}", + "FhirSourceGenerator", + DiagnosticSeverity.Info, + true); +} diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Emitter.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Emitter.cs new file mode 100644 index 000000000..b31e7e03b --- /dev/null +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Emitter.cs @@ -0,0 +1,195 @@ +using System.Reflection; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.Health.Fhir.CodeGenCommon.Models; +using Microsoft.Health.Fhir.SourceGenerator.Parsing; +using Microsoft.Health.Fhir.SpecManager.Converters; +using Microsoft.Health.Fhir.SpecManager.Language; +using Microsoft.Health.Fhir.SpecManager.Manager; +using Microsoft.Health.Fhir.SpecManager.Models; + +namespace Microsoft.Health.Fhir.SourceGenerator; + +internal class Emitter +{ + private delegate bool TryGetModel(FhirVersionInfo versionInfo, string key, out TModel? model) where TModel : class; + private readonly ILanguage _language = new CSharpFirely2(); + private readonly IFhirConverter _fhirConverter = new FromFhirExpando(); + private readonly FhirVersionInfo _fhirInfo = new FhirVersionInfo(FhirPackageCommon.FhirSequenceEnum.R4B); + private readonly ResourcePartialClass _resource; + private readonly Action _reportError; + + public Emitter( + ResourcePartialClass resource, + Action reportError) + { + _resource = resource; + _reportError = reportError; + } + + public string? Emit() + { + try + { + ProcessTerminologyArtifacts(_fhirInfo, (FhirVersionInfo m, string k, out object? v) => TryGetFhirTerminology(m, k, out v)); + + foreach (var item in _fhirInfo.ValueSetsByUrl) + { + var vs = item.Value; + foreach (var v in vs.ValueSetsByVersion) + { + v.Value.Resolve(_fhirInfo.CodeSystems); + } + } + + return ProcessStructureDefinition(_fhirInfo); + + static bool TryGetFhirTerminology(FhirVersionInfo m, string key, out object? value) + { + FhirValueSet? valueset = null; + FhirCodeSystem? codeSystem = null; + if (m.CodeSystems.TryGetValue(key, out codeSystem) || + m.TryGetValueSet(key, out valueset)) + { + value = (object)codeSystem ?? (object)valueset!; + return true; + } + else + { + value = null; + return false; + } + } + + } + catch (ReflectionTypeLoadException rex) + { + _reportError(Diagnostic.Create(DiagnosticDescriptors.TypeLoaderException, Location.None, rex.LoaderExceptions)); + } + catch (Exception ex) + { + _reportError(Diagnostic.Create(DiagnosticDescriptors.UnhandledException, Location.None, ex)); + } + + return null; + } + + private void ProcessTerminologyArtifacts( + FhirVersionInfo fhirInfo, + TryGetModel modelCollectionLocator) + where TModel : class + { + foreach (var path in _resource.TerminologyResourcePaths) + { + if (path is null) + { + continue; + } + + var model = ProcessFile(path, fhirInfo, _fhirConverter, modelCollectionLocator, out var fileName, out var canonical, out var artifactClass); + if (model == null || (artifactClass != FhirArtifactClassEnum.CodeSystem && artifactClass != FhirArtifactClassEnum.ValueSet)) + { + _reportError(Diagnostic.Create(DiagnosticDescriptors.FailedArtifactDef, Location.None, path, "CodeSystem or ValueSet")); + continue; + } + + _reportError(Diagnostic.Create(DiagnosticDescriptors.ProcessSuccess, Location.None, path, canonical, artifactClass, fhirInfo.Resources.Count)); + } + } + + + private string? ProcessStructureDefinition(FhirVersionInfo fhirInfo) + { + var structureDef = _resource.StructureDefinitionPath; + var complex = ProcessFile(structureDef, fhirInfo, _fhirConverter, m => m.Resources, out var id, out var canonical, out var artifactClass); + if (complex == null || artifactClass != FhirArtifactClassEnum.Resource) + { + _reportError(Diagnostic.Create(DiagnosticDescriptors.FailedArtifactDef, Location.None, structureDef, FhirArtifactClassEnum.Resource)); + return null; + } + + _reportError(Diagnostic.Create(DiagnosticDescriptors.ProcessSuccess, Location.None, structureDef, canonical, artifactClass, fhirInfo.Resources.Count)); + + return GenerateFhirResourceSource(fhirInfo, complex, structureDef); + + + } + + private string? GenerateFhirResourceSource(FhirVersionInfo fhirInfo, FhirComplex complex, string originalFilePath) + { + _language.Namespace = _resource.Namespace; + using var memoryStream = new MemoryStream(); + _language.Export(fhirInfo, complex, memoryStream); + memoryStream.Position = 0; + + if (memoryStream.Length == 0) + { + _reportError(Diagnostic.Create(DiagnosticDescriptors.FailedToGenerate, Location.None, originalFilePath)); + return null; + } + + var code = Encoding.UTF8.GetString(memoryStream.ToArray()); + return code; + } + + internal static TModel? ProcessFile( + string path, + FhirVersionInfo fhirInfo, + IFhirConverter fhirConverter, + Func> modelCollectionAccessor, + out string fileName, + out string? canonical, + out FhirArtifactClassEnum artifactClass) + where TModel : class + => ProcessFile(path, fhirInfo, fhirConverter, (FhirVersionInfo m, string k, out TModel? v) => modelCollectionAccessor(m).TryGetValue(k, out v), out fileName, out canonical, out artifactClass); + + private static TModel? ProcessFile( + string path, + FhirVersionInfo fhirInfo, + IFhirConverter fhirConverter, + TryGetModel modelCollectionLocator, + out string id, + out string? canonical, + out FhirArtifactClassEnum artifactClass) + where TModel : class + { + id = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path)); + + if (!File.Exists(path)) + { + canonical = null; + artifactClass = default; + return null; + } + + var json = File.ReadAllText(path); + + if (!fhirConverter.TryParseResource(json, out var resource, out _)) + { + canonical = null; + artifactClass = default; + return null; + } + + if (resource is FhirExpando expando) + { + if (expando.TryGetValue("type", out var typeVal) && typeVal is string typeName) + { + id = typeName; + } + else if (expando.TryGetValue("url", out var urlVal) && urlVal is string url) + { + id = url; + } + else if (expando.TryGetValue("id", out var idVal) && urlVal is string id2) + { + id = id2; + } + } + + fhirInfo.ProcessResource(resource, out canonical, out artifactClass); + + modelCollectionLocator(fhirInfo, id, out var model); + return model; + } +} diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs index 8a1a76eec..28484f284 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/FhirSourceGenerator.cs @@ -1,255 +1,43 @@ -using System.Reflection; -using System.Text; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; -using Microsoft.Health.Fhir.CodeGenCommon.Models; -using Microsoft.Health.Fhir.SpecManager.Converters; -using Microsoft.Health.Fhir.SpecManager.Language; -using Microsoft.Health.Fhir.SpecManager.Manager; -using Microsoft.Health.Fhir.SpecManager.Models; +using Microsoft.Health.Fhir.SourceGenerator.Parsing; namespace Microsoft.Health.Fhir.SourceGenerator { [Generator] public class FhirSourceGenerator : ISourceGenerator { - private delegate bool TryGetModel(FhirVersionInfo versionInfo, string key, out TModel model) where TModel : class; - - private static readonly DiagnosticDescriptor FailedArtifactDef = new( - "FHIRGEN001", - "Invalid artifact file", - "Unable to parse {1} file '{0}'. StructureDefinition files must have a snapshot.", - "FhirSourceGenerator", - DiagnosticSeverity.Warning, - true); - - private static readonly DiagnosticDescriptor TypeLoaderException = new( - "FHIRGEN002", - "Fatal FhirCode Generation error", - "Type loader exception '{0}'.", - "FhirSourceGenerator", - DiagnosticSeverity.Error, - true); - - private static readonly DiagnosticDescriptor UnhandledException = new( - "FHIRGEN003", - "Fatal FhirCode Generation error", - "Unhandled exception '{0}'.", - "FhirSourceGenerator", - DiagnosticSeverity.Error, - true); - - private static readonly DiagnosticDescriptor FailedToGenerate = new( - "FHIRGEN004", - "Invalid .StructureDefinition.json file", - "Failed to generate code for json file [{0}]{1}.", - "FhirSourceGenerator", - DiagnosticSeverity.Error, - true); - - private static readonly DiagnosticDescriptor ProcessSuccess = new( - "FHIRGEN005", - "Parsing success", - "JsonPath: {0} Canonical: {1}, Artifact Type: {2}, ResourceCount: {3}", - "FhirSourceGenerator", - DiagnosticSeverity.Info, - true); - - private static readonly ILanguage language = new CSharpFirely2(); - private static readonly IFhirConverter fhirConverter = new FromFhirExpando(); - - public void Execute(GeneratorExecutionContext context) - { -#if DEBUG - // System.Diagnostics.Debugger.Launch(); -#endif - - try - { - var fhirInfo = new FhirVersionInfo(FhirPackageCommon.FhirSequenceEnum.R4B); - - ProcessArtifacts(FhirArtifactClassEnum.CodeSystem, context, fhirInfo, (FhirVersionInfo m, string k, out FhirCodeSystem v) => m.CodeSystems.TryGetValue(k, out v)); - ProcessArtifacts(FhirArtifactClassEnum.ValueSet, context, fhirInfo, (FhirVersionInfo m, string k, out FhirValueSet v) => m.TryGetValueSet(k, out v)); - - foreach (var item in fhirInfo.ValueSetsByUrl) - { - var vs = item.Value; - foreach (var v in vs.ValueSetsByVersion) - { - v.Value.Resolve(fhirInfo.CodeSystems); - } - } - - ProcessStructureDefinitions(context, fhirInfo); - - } - catch (ReflectionTypeLoadException rex) - { - context.ReportDiagnostic(Diagnostic.Create(TypeLoaderException, Location.None, rex.LoaderExceptions)); - } - catch (Exception ex) - { - context.ReportDiagnostic(Diagnostic.Create(UnhandledException, Location.None, ex)); - } - } - + /// public void Initialize(GeneratorInitializationContext context) { + context.RegisterForSyntaxNotifications(SyntaxContextReceiver.Create); } - private void ProcessArtifacts( - FhirArtifactClassEnum expectedArtifactClass, - GeneratorExecutionContext context, - FhirVersionInfo fhirInfo, - TryGetModel modelCollectionLocator) - where TModel : class - { - foreach (var valueSet in context.AdditionalFiles.Where(f => f.Path.EndsWith($".{expectedArtifactClass}.json", StringComparison.InvariantCultureIgnoreCase))) - { - if (valueSet is null) - { - continue; - } - - var namespaceName = context.Compilation.AssemblyName; - - var model = ProcessFile(valueSet.Path, fhirInfo, fhirConverter, modelCollectionLocator, out var fileName, out var canonical, out var artifactClass); - if (model == null || artifactClass != expectedArtifactClass) - { - context.ReportDiagnostic(Diagnostic.Create(FailedArtifactDef, Location.None, valueSet.Path, expectedArtifactClass)); - continue; - } - - context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, valueSet.Path, canonical, artifactClass, fhirInfo.Resources.Count)); - } - } - - private void ProcessStructureDefinitions(GeneratorExecutionContext context, FhirVersionInfo fhirInfo) - { - foreach (var structureDef in context.AdditionalFiles.Where(f => f.Path.EndsWith(".StructureDefinition.json", StringComparison.InvariantCultureIgnoreCase))) - { - if (structureDef is null) - { - continue; - } - - var complex = ProcessFile(structureDef.Path, fhirInfo, fhirConverter, m => m.Resources, out var id, out var canonical, out var artifactClass); - if (complex == null || artifactClass != FhirArtifactClassEnum.Resource) - { - context.ReportDiagnostic(Diagnostic.Create(FailedArtifactDef, Location.None, structureDef.Path, FhirArtifactClassEnum.Resource)); - continue; - } - - context.ReportDiagnostic(Diagnostic.Create(ProcessSuccess, Location.None, structureDef.Path, canonical, artifactClass, fhirInfo.Resources.Count)); - - AddFhirResourceSource(context, fhirInfo, complex, structureDef.Path); - } - } - - private void AddFhirResourceSource(GeneratorExecutionContext context, FhirVersionInfo fhirInfo, FhirComplex complex, string originalFilePath) + public void Execute(GeneratorExecutionContext context) { - var namespaceName = context.Compilation.AssemblyName; - language.Namespace = GetNamespaceName(namespaceName, originalFilePath, context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.projectdir", out var projectDir) ? projectDir : null); - using var memoryStream = new MemoryStream(); - language.Export(fhirInfo, complex, memoryStream); - memoryStream.Position = 0; - - if (memoryStream.Length == 0) + if (context.SyntaxContextReceiver is not SyntaxContextReceiver receiver || receiver.ClassDeclarations.Count == 0) { - context.ReportDiagnostic(Diagnostic.Create(FailedToGenerate, Location.None, originalFilePath)); + // nothing to do yet return; } - var code = Encoding.UTF8.GetString(memoryStream.ToArray()); - - context.AddSource($"{complex.Id}.cs", SourceText.From(code, Encoding.UTF8)); - } - - private string? GetNamespaceName(string? namespaceName, string path, string? projectPath) - { - string folderName; - if (projectPath != null) - { - folderName = (Path.GetDirectoryName(path) + Path.DirectorySeparatorChar).Replace(projectPath, string.Empty); - if (folderName.EndsWith($"{Path.DirectorySeparatorChar}")) - { - folderName = folderName.Substring(0, folderName.Length - 1); - } - } - else - { - folderName = Path.GetDirectoryName(path).Split(Path.DirectorySeparatorChar).Last(); - } - - if (!string.IsNullOrEmpty(folderName) && folderName != namespaceName) - { - return $"{namespaceName}.{folderName.Replace(Path.DirectorySeparatorChar, '.')}"; - } - else - { - return namespaceName; - } - } - - internal TModel? ProcessFile( - string path, - FhirVersionInfo fhirInfo, - IFhirConverter fhirConverter, - Func> modelCollectionAccessor, - out string fileName, - out string? canonical, - out FhirArtifactClassEnum artifactClass) - where TModel : class - => ProcessFile(path, fhirInfo, fhirConverter, (FhirVersionInfo m, string k, out TModel v) => modelCollectionAccessor(m).TryGetValue(k, out v), out fileName, out canonical, out artifactClass); - - private TModel? ProcessFile( - string path, - FhirVersionInfo fhirInfo, - IFhirConverter fhirConverter, - TryGetModel modelCollectionLocator, - out string id, - out string? canonical, - out FhirArtifactClassEnum artifactClass) - where TModel : class - { - id = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path)); - - if (!File.Exists(path)) - { - canonical = null; - artifactClass = default; - return null; - } - - var json = File.ReadAllText(path); +#if DEBUG + System.Diagnostics.Debugger.Launch(); +#endif - if (!fhirConverter.TryParseResource(json, out var resource, out _)) - { - canonical = null; - artifactClass = default; - return null; - } + var parser = new Parser(context, context.ReportDiagnostic, context.CancellationToken); + var resourcePartialClasses = parser.GetResourcePartialClasses(receiver.ClassDeclarations); - if (resource is FhirExpando expando) + foreach (var resourceClass in resourcePartialClasses) { - if (expando.TryGetValue("type", out var typeVal) && typeVal is string typeName) - { - id = typeName; - } - else if(expando.TryGetValue("url", out var urlVal) && urlVal is string url) - { - id = url; - } - else if (expando.TryGetValue("id", out var idVal) && urlVal is string id2) + var emitter = new Emitter(resourceClass, context.ReportDiagnostic); + var code = emitter.Emit(); + if (!string.IsNullOrEmpty(code)) { - id = id2; + context.AddSource($"{resourceClass.Name}.cs", SourceText.From(code!, Encoding.UTF8)); } } - - fhirInfo.ProcessResource(resource, out canonical, out artifactClass); - - modelCollectionLocator(fhirInfo, id, out var model); - return model; } } } diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj b/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj index d62433869..93e0defe1 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Microsoft.Health.Fhir.SourceGenerator.csproj @@ -5,14 +5,6 @@ 11 true enable - true - true - - 0.1.0-beta1 - true - analyzers\cs - embedded - true @@ -27,19 +19,10 @@ - - - - - - - - - - - - - + + all + runtime; build; native; contentfiles; analyzers + @@ -66,7 +49,7 @@ true Microsoft.Health.Fhir.CodeGenCommon.dll - + true Microsoft.Health.Fhir.SpecManager.dll diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Helpers.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Helpers.cs new file mode 100644 index 000000000..804497683 --- /dev/null +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Helpers.cs @@ -0,0 +1,129 @@ +using System.Reflection; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Health.Fhir.SourceGenerator.Parsing; + +internal static class Helpers +{ + public static INamedTypeSymbol? GetBestTypeByMetadataName(this Compilation compilation, string fullyQualifiedMetadataName) + { + // Try to get the unique type with this name, ignoring accessibility + var type = compilation.GetTypeByMetadataName(fullyQualifiedMetadataName); + + // Otherwise, try to get the unique type with this name originally defined in 'compilation' + type ??= compilation.Assembly.GetTypeByMetadataName(fullyQualifiedMetadataName); + + // Otherwise, try to get the unique accessible type with this name from a reference + if (type is null) + { + foreach (var module in compilation.Assembly.Modules) + { + foreach (var referencedAssembly in module.ReferencedAssemblySymbols) + { + var currentType = referencedAssembly.GetTypeByMetadataName(fullyQualifiedMetadataName); + if (currentType is null) + { + continue; + } + + switch (currentType.GetResultantVisibility()) + { + case SymbolVisibility.Public: + case SymbolVisibility.Internal when referencedAssembly.GivesAccessTo(compilation.Assembly): + break; + + default: + continue; + } + + if (type is object) + { + // Multiple visible types with the same metadata name are present + return null; + } + + type = currentType; + } + } + } + + return type; + } + + private static SymbolVisibility GetResultantVisibility(this ISymbol symbol) + { + // Start by assuming it's visible. + SymbolVisibility visibility = SymbolVisibility.Public; + + switch (symbol.Kind) + { + case SymbolKind.Alias: + // Aliases are uber private. They're only visible in the same file that they + // were declared in. + return SymbolVisibility.Private; + + case SymbolKind.Parameter: + // Parameters are only as visible as their containing symbol + return symbol.ContainingSymbol.GetResultantVisibility(); + + case SymbolKind.TypeParameter: + // Type Parameters are private. + return SymbolVisibility.Private; + } + + while (symbol != null && symbol.Kind != SymbolKind.Namespace) + { + switch (symbol.DeclaredAccessibility) + { + // If we see anything private, then the symbol is private. + case Accessibility.NotApplicable: + case Accessibility.Private: + return SymbolVisibility.Private; + + // If we see anything internal, then knock it down from public to + // internal. + case Accessibility.Internal: + case Accessibility.ProtectedAndInternal: + visibility = SymbolVisibility.Internal; + break; + + // For anything else (Public, Protected, ProtectedOrInternal), the + // symbol stays at the level we've gotten so far. + } + + symbol = symbol.ContainingSymbol; + } + + return visibility; + } + + public static void Deconstruct(this KeyValuePair pair, out TKey key, out TValue value) + { + key = pair.Key; + value = pair.Value; + } + + public static string GetCSharpFullName(this Type propertyType) + { + if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition().FullName == typeof(Nullable<>).FullName) + { + return $"{propertyType.GetGenericArguments()[0].GetCSharpFullName()}?"; + } + else + { + return propertyType.FullName.Replace('+', '.'); + } + } + + public static string GetDisplayName(this MethodInfo method, string methodName) + { + if (method.IsGenericMethod) + { + return $"{methodName}__{string.Join("_", method.GetGenericArguments().Select(x => x.Name))}"; + } + else + { + return methodName; + } + } +} diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs new file mode 100644 index 000000000..66c67fc9c --- /dev/null +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs @@ -0,0 +1,207 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Configuration; +using System.Diagnostics; +using System.Text; +using System.Threading; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Health.Fhir.SourceGenerator.Parsing; + +internal class Parser +{ + internal const string GeneratedFhirAttributeName = "Microsoft.Health.Fhir.CodeGeneration.GeneratedFhirAttribute"; + private readonly GeneratorExecutionContext _context; + private readonly Action _reportDiagnostic; + private readonly CancellationToken _cancellationToken; + + public Parser(GeneratorExecutionContext context, Action reportDiagnostic, CancellationToken cancellationToken) + { + _context = context; + _reportDiagnostic = reportDiagnostic; + _cancellationToken = cancellationToken; + } + + internal IReadOnlyList GetResourcePartialClasses(IEnumerable classes) + { + _context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.projectdir", out var projectDir); + + INamedTypeSymbol? generateServiceRegistrationAttribute = _context.Compilation.GetBestTypeByMetadataName(GeneratedFhirAttributeName); + if (generateServiceRegistrationAttribute == null) + { + // nothing to do if this type isn't available + return Array.Empty(); + } + + + var result = new List(); + + foreach (IGrouping group in classes.GroupBy(x => x.SyntaxTree)) + { + SyntaxTree syntaxTree = group.Key; + SemanticModel sm = _context.Compilation.GetSemanticModel(syntaxTree); + + foreach (ClassDeclarationSyntax classDec in group) + { + // stop if we're asked to + _cancellationToken.ThrowIfCancellationRequested(); + + string nspace = string.Empty; + var classDecSymbol = sm.GetDeclaredSymbol(classDec); + + if (classDecSymbol == null) + { + continue; + } + + string? structureDefPath = null; + string[] terminologies = Array.Empty(); + + foreach (AttributeListSyntax mal in classDec.AttributeLists) + { + foreach (AttributeSyntax ma in mal.Attributes) + { + IMethodSymbol? attrCtorSymbol = sm.GetSymbolInfo(ma, _cancellationToken).Symbol as IMethodSymbol; + if (attrCtorSymbol == null || !generateServiceRegistrationAttribute.Equals(attrCtorSymbol.ContainingType, SymbolEqualityComparer.Default)) + { + // badly formed attribute definition, or not the right attribute + continue; + } + + bool hasMisconfiguredInput = false; + ImmutableArray boundAttributes = classDecSymbol!.GetAttributes(); + + if (boundAttributes.Length == 0) + { + continue; + } + + foreach (AttributeData attributeData in boundAttributes) + { + if (!SymbolEqualityComparer.Default.Equals(attributeData.AttributeClass, generateServiceRegistrationAttribute)) + { + continue; + } + + // supports: [GeneratedFhir("Path/To/Resource.json")] + // supports: [GeneratedFhir(structureDefinitionPath: "Path/To/Resource.json")] + if (attributeData.ConstructorArguments.Any()) + { + foreach (TypedConstant typedConstant in attributeData.ConstructorArguments) + { + if (typedConstant.Kind == TypedConstantKind.Error) + { + hasMisconfiguredInput = true; + break; // if a compilation error was found, no need to keep evaluating other args + } + } + + ImmutableArray items = attributeData.ConstructorArguments; + + switch (items.Length) + { + case 1: + // GenerateServiceRegistration(string configurationSection) + structureDefPath = (string)GetItem(items[0])!; + break; + + default: + Debug.Assert(false, "Unexpected number of arguments in attribute constructor."); + break; + } + } + + // argument syntax takes parameters. e.g. EventId = 0 + // supports: e.g. [GeneratedFhir("Path/To/Resource.json", TerminologyResources = new []{ "Path/To/ValueSet.json" })] + if (attributeData.NamedArguments.Any()) + { + foreach (KeyValuePair namedArgument in attributeData.NamedArguments) + { + TypedConstant typedConstant = namedArgument.Value; + if (typedConstant.Kind == TypedConstantKind.Error) + { + hasMisconfiguredInput = true; + break; // if a compilation error was found, no need to keep evaluating other args + } + else + { + TypedConstant value = namedArgument.Value; + switch (namedArgument.Key) + { + case "TerminologyResources": + var values = (ImmutableArray)GetItem(value)!; + terminologies = values.Select(x => x.Value?.ToString()).Where(x => !string.IsNullOrEmpty(x)).ToArray()!; + break; + } + } + } + } + + if (hasMisconfiguredInput) + { + // skip further generator execution and let compiler generate the errors + break; + } + + static object? GetItem(TypedConstant arg) => arg.Kind == TypedConstantKind.Array ? arg.Values : arg.Value; + } + } + } + + if (structureDefPath != null) + { + // determine the namespace the class is declared in, if any + SyntaxNode? potentialNamespaceParent = classDec.Parent; + while (potentialNamespaceParent != null && + potentialNamespaceParent is not NamespaceDeclarationSyntax && + potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax) + { + potentialNamespaceParent = potentialNamespaceParent.Parent; + } + + if (potentialNamespaceParent is FileScopedNamespaceDeclarationSyntax fileScopedNamespace) + { + nspace = fileScopedNamespace.Name.ToString(); + } + else if (potentialNamespaceParent is NamespaceDeclarationSyntax namespaceParent) + { + nspace = namespaceParent.Name.ToString(); + while (true) + { + if (namespaceParent.Parent is not NamespaceDeclarationSyntax namespaceDeclaration) + { + break; + } + else + { + namespaceParent = namespaceDeclaration; + } + + nspace = $"{namespaceParent.Name}.{nspace}"; + } + } + + result.Add(new ResourcePartialClass(nspace, classDecSymbol.Name, ResolvePath(structureDefPath), terminologies.Select(ResolvePath).ToArray())); + + string ResolvePath(string path) + { + path = Path.Combine(path.Split('/', '\\')); + var found = _context.AdditionalFiles.Where(x => x.Path.EndsWith(path)).Select(x => x.Path).FirstOrDefault(); + if (found == null && projectDir != null) + { + found = Path.Combine(projectDir, path); + } + + Debug.Assert(File.Exists(found), $"File {found} does not exist"); + + return found; + } + } + } + } + + return result; + } +} diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/ResourcePartialClass.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/ResourcePartialClass.cs new file mode 100644 index 000000000..69b587a30 --- /dev/null +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/ResourcePartialClass.cs @@ -0,0 +1,3 @@ +namespace Microsoft.Health.Fhir.SourceGenerator.Parsing; + +internal record class ResourcePartialClass(string Namespace, string Name, string StructureDefinitionPath, string[] TerminologyResourcePaths); diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/SymbolVisibility.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/SymbolVisibility.cs new file mode 100644 index 000000000..b9f28b3b9 --- /dev/null +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/SymbolVisibility.cs @@ -0,0 +1,8 @@ +namespace Microsoft.Health.Fhir.SourceGenerator.Parsing; + +internal enum SymbolVisibility +{ + Public, + Private, + Internal, +} diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/SyntaxContextReceiver.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/SyntaxContextReceiver.cs new file mode 100644 index 000000000..6f10b1bdb --- /dev/null +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/SyntaxContextReceiver.cs @@ -0,0 +1,57 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Health.Fhir.SourceGenerator.Parsing +{ + internal sealed class SyntaxContextReceiver : ISyntaxContextReceiver + { + public HashSet ClassDeclarations { get; } = new(); + + internal static SyntaxContextReceiver Create() + { + return new SyntaxContextReceiver(); + } + + public void OnVisitSyntaxNode(GeneratorSyntaxContext context) + { + if (IsSyntaxTargetForGeneration(context.Node)) + { + var classSyntax = GetSemanticTargetForGeneration(context); + if (classSyntax != null) + { + ClassDeclarations.Add(classSyntax); + } + } + } + + private static bool IsSyntaxTargetForGeneration(SyntaxNode node) => + node is ClassDeclarationSyntax cls && cls.AttributeLists.Count > 0; + + private static ClassDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext context) + { + var classDeclarationSyntax = (ClassDeclarationSyntax)context.Node; + + foreach (AttributeListSyntax attributeListSyntax in classDeclarationSyntax.AttributeLists) + { + foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) + { + var attributeSymbol = context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol; + if (attributeSymbol == null) + { + continue; + } + + INamedTypeSymbol attributeContainingTypeSymbol = attributeSymbol.ContainingType; + string fullName = attributeContainingTypeSymbol.ToDisplayString(); + + if (fullName == Parser.GeneratedFhirAttributeName) + { + return classDeclarationSyntax; + } + } + } + + return null; + } + } +} From d5b15ddde1b707f5b9529db373e03b109ca7aebd Mon Sep 17 00:00:00 2001 From: almostchristian Date: Mon, 16 Oct 2023 16:18:47 +0800 Subject: [PATCH 10/15] Regenerate snapshots from forge --- .../Education.StructureDefinition.json | 930 ++- .../Models/Patient.StructureDefinition.json | 7327 +++++++++-------- .../Models/Pokemon.StructureDefinition.json | 807 +- 3 files changed, 5655 insertions(+), 3409 deletions(-) diff --git a/SampleSourceGen/Education.StructureDefinition.json b/SampleSourceGen/Education.StructureDefinition.json index 794ba4f90..1ff38d3ec 100644 --- a/SampleSourceGen/Education.StructureDefinition.json +++ b/SampleSourceGen/Education.StructureDefinition.json @@ -1,99 +1,851 @@ { - "resourceType": "StructureDefinition", - "id": "Education", - "url": "http://hl7.org/fhir/StructureDefinition/Education", - "version": "0.1", - "name": "Education", - "status": "draft", - "publisher": "Firely", - "description": "Study or other form of education that a person has done.", - "copyright": "Copyright (C) 2019 Firely", - "fhirVersion": "4.0.1", - "kind": "resource", - "abstract": false, - "type": "Education", - "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", - "derivation": "specialization", - "snapshot": { - "element": [ + "resourceType": "StructureDefinition", + "id": "Education", + "url": "http://hl7.org/fhir/StructureDefinition/Education", + "version": "0.1", + "name": "Education", + "status": "draft", + "publisher": "Firely", + "description": "Study or other form of education that a person has done.", + "copyright": "Copyright (C) 2019 Firely", + "fhirVersion": "4.3.0", + "kind": "resource", + "abstract": false, + "type": "Education", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", + "derivation": "specialization", + "snapshot": { + "element": [ + { + "id": "Education", + "path": "Education", + "short": "A resource with narrative, extensions, and contained resources", + "definition": "A resource that includes narrative, extensions, and contained resources.", + "min": 0, + "max": "*", + "base": { + "path": "Education", + "min": 0, + "max": "*" + }, + "constraint": [ + { + "key": "dom-2", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL NOT contain nested Resources", + "expression": "contained.contained.empty()", + "xpath": "not(parent::f:contained and f:contained)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-4", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated", + "expression": "contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:versionId)) and not(exists(f:contained/*/f:meta/f:lastUpdated))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-3", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource", + "expression": "contained.where(((id.exists() and ('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url)))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(uri) = '#').exists()).not()).trace('unmatched', id).empty()", + "xpath": "not(exists(for $contained in f:contained return $contained[not(exists(parent::*/descendant::f:reference/@value=concat('#', $contained/*/f:id/@value)) or exists(descendant::f:reference[@value='#']))]))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice", + "valueBoolean": true + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation", + "valueMarkdown": "When a resource has no narrative, only systems that fully understand the data can display the resource to a human safely. Including a human readable representation in the resource makes for a much more robust eco-system and cheaper handling of resources by intermediary systems. Some ecosystems restrict distribution of resources to only those systems that do fully understand the resources, and as a consequence implementers may believe that the narrative is superfluous. However experience shows that such eco-systems often open up to new participants over time." + } + ], + "key": "dom-6", + "severity": "warning", + "human": "A resource should have narrative for robust management", + "expression": "text.`div`.exists()", + "xpath": "exists(f:text/h:div)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-5", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a security label", + "expression": "contained.meta.security.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:security))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Entity. Role, or Act" + } + ] + }, + { + "id": "Education.id", + "path": "Education.id", + "short": "Logical id of this artifact", + "definition": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "comment": "The only time that a resource does not have an id is when it is being submitted to the server using a create operation.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "id" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true + }, + { + "id": "Education.meta", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Education.meta", + "short": "Metadata about the resource", + "definition": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.meta", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Meta" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Education.implicitRules", + "path": "Education.implicitRules", + "short": "A set of rules under which this content was created", + "definition": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "comment": "Asserting this rule set restricts the content to be only understood by a limited set of trading partners. This inherently limits the usefulness of the data in the long term. However, the existing health eco-system is highly fractured, and not yet ready to define, collect, and exchange data in a generally computable sense. Wherever possible, implementers and/or specification writers should avoid using this element. Often, when used, the URL is a reference to an implementation guide that defines these special rules as part of it's narrative along with other profiles, value sets, etc.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.implicitRules", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "uri" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because the implicit rules may provide additional knowledge about the resource that modifies it's meaning or interpretation", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Education.language", + "path": "Education.language", + "short": "Language of the resource content", + "definition": "The base language in which the resource is written.", + "comment": "Language is provided to support indexing and accessibility (typically, services such as text to speech use the language tag). The html language tag in the narrative applies to the narrative. The language tag on the resource may be used to specify the language of other presentations generated from the data in the resource. Not all the content has to be in the base language. The Resource.language should not be assumed to apply to the narrative automatically. If a language is specified, it should it also be specified on the div element in the html (see rules in HTML5 for information about the relationship between xml:lang and the html lang attribute).", + "min": 0, + "max": "1", + "base": { + "path": "Resource.language", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ { - "id": "Education", - "path": "Education", - "description": "Study or other form of education that a person has done.", - "min": 0, - "max": "*", - "mustSupport": false, - "isModifier": false, - "isSummary": false + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" }, { - "id": "Education.subject", - "path": "Education.subject", - "short": "Who was educated?", - "definition": "Person who has done this education.", - "min": 1, - "max": "1", - "type": [ - { - "code": "Reference", - "targetProfile": "http://hl7.org/fhir/StructureDefinition/Person" - }, - { - "code": "Reference", - "targetProfile": "http://hl7.org/fhir/StructureDefinition/Patient" - }, - { - "code": "Reference", - "targetProfile": "http://hl7.org/fhir/StructureDefinition/Practitioner" - } - ] + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" }, { - "id": "Education.institute", - "path": "Education.institute", - "short": "Where did you do this study?", - "definition": "Educational institute, like a university or training company", - "min": 0, - "max": "1", - "type": [ - { - "code": "Reference", - "targetProfile": "http://hl7.org/fhir/StructureDefinition/Organization" - } - ] - }, + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Education.text", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Education.text", + "short": "Text summary of the resource, for human interpretation", + "definition": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "comment": "Contained resources do not have narrative. Resources that are not contained SHOULD have a narrative. In some cases, a resource may only have text with little or no additional discrete data (as long as all minOccurs=1 elements are satisfied). This may be necessary for data from legacy systems where information is captured as a \"text blob\" or where text is additionally entered raw or narrated and encoded information is added later.", + "alias": [ + "narrative", + "html", + "xhtml", + "display" + ], + "min": 0, + "max": "1", + "base": { + "path": "DomainResource.text", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Narrative" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + }, + { + "identity": "rim", + "map": "Act.text?" + } + ] + }, + { + "id": "Education.contained", + "path": "Education.contained", + "short": "Contained, inline Resources", + "definition": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, and nor can they have their own independent transaction scope.", + "comment": "This should never be done when the content can be identified properly, as once identification is lost, it is extremely difficult (and context dependent) to restore it again. Contained resources may have profiles and tags In their meta elements, but SHALL NOT have security labels.", + "alias": [ + "inline resources", + "anonymous resources", + "contained resources" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.contained", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Resource" + } + ], + "constraint": [ + { + "key": "dom-r4b", + "severity": "warning", + "human": "Containing new R4B resources within R4 resources may cause interoperability issues if instances are shared with R4 systems", + "expression": "($this is Citation or $this is Evidence or $this is EvidenceReport or $this is EvidenceVariable or $this is MedicinalProductDefinition or $this is PackagedProductDefinition or $this is AdministrableProductDefinition or $this is Ingredient or $this is ClinicalUseDefinition or $this is RegulatedAuthorization or $this is SubstanceDefinition or $this is SubscriptionStatus or $this is SubscriptionTopic) implies (%resource is Citation or %resource is Evidence or %resource is EvidenceReport or %resource is EvidenceVariable or %resource is MedicinalProductDefinition or %resource is PackagedProductDefinition or %resource is AdministrableProductDefinition or %resource is Ingredient or %resource is ClinicalUseDefinition or %resource is RegulatedAuthorization or %resource is SubstanceDefinition or %resource is SubscriptionStatus or %resource is SubscriptionTopic)", + "xpath": "not(f:Citation|f:Evidence|f:EvidenceReport|f:EvidenceVariable|f:MedicinalProductDefinition|f:PackagedProductDefinition|f:AdministrableProductDefinition|f:Ingredient|f:ClinicalUseDefinition|f:RegulatedAuthorization|f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic) or not(parent::f:Citation|parent::f:Evidence|parent::f:EvidenceReport|parent::f:EvidenceVariable|parent::f:MedicinalProductDefinition|parent::f:PackagedProductDefinition|parent::f:AdministrableProductDefinition|parent::f:Ingredient|parent::f:ClinicalUseDefinition|parent::f:RegulatedAuthorization|parent::f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Entity. Role, or Act" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Education.extension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Education.extension", + "slicing": { + "discriminator": [ { - "id": "Education.study", - "path": "Education.study", - "short": "What study?", - "definition": "Name of the study that the subject followed.", - "min": 1, - "max": "1", - "type": [ - { - "code": "string", - "profile": "http://hl7.org/fhir/StructureDefinition/string" - } - ] - }, + "type": "value", + "path": "url" + } + ], + "description": "Extensions are always sliced by (at least) url", + "rules": "open" + }, + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Education.modifierExtension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Education.modifierExtension", + "slicing": { + "discriminator": [ { - "id": "Education.graduated[x]", - "path": "Education.graduated[x]", - "short": "Did subject graduate for the study?", - "definition": "Did the subject graduate for the study? If possible enter the date of graduation.", - "min": 1, - "max": "1", - "type": [ - { - "code": "boolean", - "profile": "http://hl7.org/fhir/StructureDefinition/boolean" - }, - { - "code": "date", - "profile": "http://hl7.org/fhir/StructureDefinition/date" - } - ] + "type": "value", + "path": "url" } + ], + "description": "Extensions are always sliced by (at least) url", + "rules": "open" + }, + "short": "Extensions that cannot be ignored", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the resource that contains them", + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Education.subject", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Education.subject", + "short": "Who was educated?", + "definition": "Person who has done this education.", + "comment": "References SHALL be a reference to an actual FHIR resource, and SHALL be resolveable (allowing for access control, temporary unavailability, etc.). Resolution can be either by retrieval from the URL, or, where applicable by resource type, by treating an absolute reference as a canonical URL and looking it up in a local registry/repository.", + "min": 1, + "max": "1", + "base": { + "path": "Education.subject", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Person", + "http://hl7.org/fhir/StructureDefinition/Patient", + "http://hl7.org/fhir/StructureDefinition/Practitioner" + ] + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ref-1", + "severity": "error", + "human": "SHALL have a contained resource if a local reference is provided", + "expression": "reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids')) or (reference='#' and %rootResource!=%resource)", + "xpath": "not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])", + "source": "http://hl7.org/fhir/StructureDefinition/Reference" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "The target of a resource reference is a RIM entry point (Act, Role, or Entity)" + } + ] + }, + { + "id": "Education.institute", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Education.institute", + "short": "Where did you do this study?", + "definition": "Educational institute, like a university or training company", + "comment": "References SHALL be a reference to an actual FHIR resource, and SHALL be resolveable (allowing for access control, temporary unavailability, etc.). Resolution can be either by retrieval from the URL, or, where applicable by resource type, by treating an absolute reference as a canonical URL and looking it up in a local registry/repository.", + "min": 0, + "max": "1", + "base": { + "path": "Education.institute", + "max": "1" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization" + ] + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ref-1", + "severity": "error", + "human": "SHALL have a contained resource if a local reference is provided", + "expression": "reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids')) or (reference='#' and %rootResource!=%resource)", + "xpath": "not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])", + "source": "http://hl7.org/fhir/StructureDefinition/Reference" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "The target of a resource reference is a RIM entry point (Act, Role, or Entity)" + } + ] + }, + { + "id": "Education.study", + "path": "Education.study", + "short": "What study?", + "definition": "Name of the study that the subject followed.", + "comment": "Note that FHIR strings SHALL NOT exceed 1MB in size", + "min": 1, + "max": "1", + "base": { + "path": "Education.study", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "string", + "profile": [ + "http://hl7.org/fhir/StructureDefinition/string" + ] + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Education.graduated[x]", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Education.graduated[x]", + "short": "Did subject graduate for the study?", + "definition": "Did the subject graduate for the study? If possible enter the date of graduation.", + "min": 1, + "max": "1", + "base": { + "path": "Education.graduated[x]", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "boolean", + "profile": [ + "http://hl7.org/fhir/StructureDefinition/boolean" + ] + }, + { + "code": "date", + "profile": [ + "http://hl7.org/fhir/StructureDefinition/date" + ] + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + } + ] + }, + "differential": { + "element": [ + { + "id": "Education", + "path": "Education", + "isSummary": false + }, + { + "id": "Education.subject", + "path": "Education.subject", + "short": "Who was educated?", + "definition": "Person who has done this education.", + "min": 1, + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Person", + "http://hl7.org/fhir/StructureDefinition/Patient", + "http://hl7.org/fhir/StructureDefinition/Practitioner" + ] + } + ] + }, + { + "id": "Education.institute", + "path": "Education.institute", + "short": "Where did you do this study?", + "definition": "Educational institute, like a university or training company", + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization" + ] + } + ] + }, + { + "id": "Education.study", + "path": "Education.study", + "short": "What study?", + "definition": "Name of the study that the subject followed.", + "min": 1, + "max": "1", + "type": [ + { + "code": "string", + "profile": [ + "http://hl7.org/fhir/StructureDefinition/string" + ] + } + ] + }, + { + "id": "Education.graduated[x]", + "path": "Education.graduated[x]", + "short": "Did subject graduate for the study?", + "definition": "Did the subject graduate for the study? If possible enter the date of graduation.", + "min": 1, + "max": "1", + "type": [ + { + "code": "boolean", + "profile": [ + "http://hl7.org/fhir/StructureDefinition/boolean" + ] + }, + { + "code": "date", + "profile": [ + "http://hl7.org/fhir/StructureDefinition/date" + ] + } ] - } -} + } + ] + } +} \ No newline at end of file diff --git a/SampleSourceGen/Models/Patient.StructureDefinition.json b/SampleSourceGen/Models/Patient.StructureDefinition.json index 55585265f..099d3830e 100644 --- a/SampleSourceGen/Models/Patient.StructureDefinition.json +++ b/SampleSourceGen/Models/Patient.StructureDefinition.json @@ -1,3286 +1,4095 @@ { - "resourceType": "StructureDefinition", - "id": "Patient", - "meta": { - "lastUpdated": "2022-05-28T12:47:40.239+10:00" + "resourceType": "StructureDefinition", + "id": "Patient", + "meta": { + "lastUpdated": "2023-10-16T08:11:00.1930053+00:00" + }, + "text": { + "status": "generated", + "div": "
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
NameFlagsCard.TypeDescription & Constraints\"doco\"
\".\"\".\" Patient NDomainResourceInformation about an individual or animal receiving health care services
Elements defined in Ancestors: id, meta, implicitRules, language, text, contained, extension, modifierExtension
\".\"\".\"\".\" identifier Σ0..*IdentifierAn identifier for this patient
\".\"\".\"\".\" active ?!Σ0..1booleanWhether this patient's record is in active use
\".\"\".\"\".\" name Σ0..*HumanNameA name associated with the patient
\".\"\".\"\".\" telecom Σ0..*ContactPointA contact detail for the individual
\".\"\".\"\".\" gender Σ0..1codemale | female | other | unknown
AdministrativeGender (Required)
\".\"\".\"\".\" birthDate Σ0..1dateThe date of birth for the individual
\".\"\".\"\".\" deceased[x] ?!Σ0..1Indicates if the individual is deceased or not
\".\"\".\"\".\"\".\" deceasedBooleanboolean
\".\"\".\"\".\"\".\" deceasedDateTimedateTime
\".\"\".\"\".\" address Σ0..*AddressAn address for the individual
\".\"\".\"\".\" maritalStatus 0..1CodeableConceptMarital (civil) status of a patient
MaritalStatus (Extensible)
\".\"\".\"\".\" multipleBirth[x] 0..1Whether patient is part of a multiple birth
\".\"\".\"\".\"\".\" multipleBirthBooleanboolean
\".\"\".\"\".\"\".\" multipleBirthIntegerinteger
\".\"\".\"\".\" photo 0..*AttachmentImage of the patient
\".\"\".\"\".\" contact I0..*BackboneElementA contact party (e.g. guardian, partner, friend) for the patient
+ Rule: SHALL at least contain a contact's details or a reference to an organization
\".\"\".\"\".\"\".\" relationship 0..*CodeableConceptThe kind of relationship
Patient Contact Relationship (Extensible)
\".\"\".\"\".\"\".\" name 0..1HumanNameA name associated with the contact person
\".\"\".\"\".\"\".\" telecom 0..*ContactPointA contact detail for the person
\".\"\".\"\".\"\".\" address 0..1AddressAddress for the contact person
\".\"\".\"\".\"\".\" gender 0..1codemale | female | other | unknown
AdministrativeGender (Required)
\".\"\".\"\".\"\".\" organization I0..1Reference(Organization)Organization that is associated with the contact
\".\"\".\"\".\"\".\" period 0..1PeriodThe period during which this contact person or organization is valid to be contacted relating to this patient
\".\"\".\"\".\" communication 0..*BackboneElementA language which may be used to communicate with the patient about his or her health
\".\"\".\"\".\"\".\" language 1..1CodeableConceptThe language which can be used to communicate with the patient about his or her health
Common Languages (Preferred but limited to AllLanguages)
\".\"\".\"\".\"\".\" preferred 0..1booleanLanguage preference indicator
\".\"\".\"\".\" generalPractitioner 0..*Reference(Organization | Practitioner | PractitionerRole)Patient's nominated primary care provider
\".\"\".\"\".\" managingOrganization Σ0..1Reference(Organization)Organization that is the custodian of the patient record
\".\"\".\"\".\" link ?!Σ0..*BackboneElementLink to another patient resource that concerns the same actual person
\".\"\".\"\".\"\".\" other Σ1..1Reference(Patient | RelatedPerson)The other patient or related person resource that the link refers to
\".\"\".\"\".\"\".\" type Σ1..1codereplaced-by | replaces | refer | seealso
LinkType (Required)

\"doco\" Documentation for this format
" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-category", + "valueString": "Base.Individuals" }, - "text": { - "status": "generated", - "div": "
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
NameFlagsCard.TypeDescription & Constraints\"doco\"
\".\"\".\" Patient NDomainResourceInformation about an individual or animal receiving health care services
Elements defined in Ancestors: id, meta, implicitRules, language, text, contained, extension, modifierExtension
\".\"\".\"\".\" identifier Σ0..*IdentifierAn identifier for this patient
\".\"\".\"\".\" active ?!Σ0..1booleanWhether this patient's record is in active use
\".\"\".\"\".\" name Σ0..*HumanNameA name associated with the patient
\".\"\".\"\".\" telecom Σ0..*ContactPointA contact detail for the individual
\".\"\".\"\".\" gender Σ0..1codemale | female | other | unknown
AdministrativeGender (Required)
\".\"\".\"\".\" birthDate Σ0..1dateThe date of birth for the individual
\".\"\".\"\".\" deceased[x] ?!Σ0..1Indicates if the individual is deceased or not
\".\"\".\"\".\"\".\" deceasedBooleanboolean
\".\"\".\"\".\"\".\" deceasedDateTimedateTime
\".\"\".\"\".\" address Σ0..*AddressAn address for the individual
\".\"\".\"\".\" maritalStatus 0..1CodeableConceptMarital (civil) status of a patient
MaritalStatus (Extensible)
\".\"\".\"\".\" multipleBirth[x] 0..1Whether patient is part of a multiple birth
\".\"\".\"\".\"\".\" multipleBirthBooleanboolean
\".\"\".\"\".\"\".\" multipleBirthIntegerinteger
\".\"\".\"\".\" photo 0..*AttachmentImage of the patient
\".\"\".\"\".\" contact I0..*BackboneElementA contact party (e.g. guardian, partner, friend) for the patient
+ Rule: SHALL at least contain a contact's details or a reference to an organization
\".\"\".\"\".\"\".\" relationship 0..*CodeableConceptThe kind of relationship
Patient Contact Relationship (Extensible)
\".\"\".\"\".\"\".\" name 0..1HumanNameA name associated with the contact person
\".\"\".\"\".\"\".\" telecom 0..*ContactPointA contact detail for the person
\".\"\".\"\".\"\".\" address 0..1AddressAddress for the contact person
\".\"\".\"\".\"\".\" gender 0..1codemale | female | other | unknown
AdministrativeGender (Required)
\".\"\".\"\".\"\".\" organization I0..1Reference(Organization)Organization that is associated with the contact
\".\"\".\"\".\"\".\" period 0..1PeriodThe period during which this contact person or organization is valid to be contacted relating to this patient
\".\"\".\"\".\" communication 0..*BackboneElementA language which may be used to communicate with the patient about his or her health
\".\"\".\"\".\"\".\" language 1..1CodeableConceptThe language which can be used to communicate with the patient about his or her health
Common Languages (Preferred but limited to AllLanguages)
\".\"\".\"\".\"\".\" preferred 0..1booleanLanguage preference indicator
\".\"\".\"\".\" generalPractitioner 0..*Reference(Organization | Practitioner | PractitionerRole)Patient's nominated primary care provider
\".\"\".\"\".\" managingOrganization Σ0..1Reference(Organization)Organization that is the custodian of the patient record
\".\"\".\"\".\" link ?!Σ0..*BackboneElementLink to another patient resource that concerns the same actual person
\".\"\".\"\".\"\".\" other Σ1..1Reference(Patient | RelatedPerson)The other patient or related person resource that the link refers to
\".\"\".\"\".\"\".\" type Σ1..1codereplaced-by | replaces | refer | seealso
LinkType (Required)

\"doco\" Documentation for this format
" + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" }, - "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm", + "valueInteger": 5 + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-security-category", + "valueCode": "patient" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg", + "valueCode": "pa" + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/Patient", + "version": "4.3.0", + "name": "Patient", + "status": "active", + "experimental": false, + "date": "2022-05-28T12:47:40+10:00", + "publisher": "Health Level Seven International (Patient Administration)", + "contact": [ + { + "telecom": [ { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-category", - "valueString": "Base.Individuals" - }, + "system": "url", + "value": "http://hl7.org/fhir" + } + ] + }, + { + "telecom": [ { + "system": "url", + "value": "http://www.hl7.org/Special/committees/pafm/index.cfm" + } + ] + } + ], + "description": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", + "purpose": "Tracking patient is the center of the healthcare process.", + "fhirVersion": "4.3.0", + "mapping": [ + { + "identity": "rim", + "uri": "http://hl7.org/v3", + "name": "RIM Mapping" + }, + { + "identity": "cda", + "uri": "http://hl7.org/v3/cda", + "name": "CDA (R2)" + }, + { + "identity": "w5", + "uri": "http://hl7.org/fhir/fivews", + "name": "FiveWs Pattern Mapping" + }, + { + "identity": "v2", + "uri": "http://hl7.org/v2", + "name": "HL7 v2 Mapping" + }, + { + "identity": "loinc", + "uri": "http://loinc.org", + "name": "LOINC code for the element" + } + ], + "kind": "resource", + "abstract": false, + "type": "Patient", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", + "derivation": "specialization", + "snapshot": { + "element": [ + { + "id": "Patient", + "path": "Patient", + "short": "Information about an individual or animal receiving health care services", + "definition": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", + "alias": [ + "SubjectOfCare Client Resident" + ], + "min": 0, + "max": "*", + "base": { + "path": "Patient", + "min": 0, + "max": "*" + }, + "constraint": [ + { + "key": "dom-2", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL NOT contain nested Resources", + "expression": "contained.contained.empty()", + "xpath": "not(parent::f:contained and f:contained)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-4", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated", + "expression": "contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:versionId)) and not(exists(f:contained/*/f:meta/f:lastUpdated))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-3", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource", + "expression": "contained.where(((id.exists() and ('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url)))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(uri) = '#').exists()).not()).trace('unmatched', id).empty()", + "xpath": "not(exists(for $contained in f:contained return $contained[not(exists(parent::*/descendant::f:reference/@value=concat('#', $contained/*/f:id/@value)) or exists(descendant::f:reference[@value='#']))]))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice", + "valueBoolean": true + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation", + "valueMarkdown": "When a resource has no narrative, only systems that fully understand the data can display the resource to a human safely. Including a human readable representation in the resource makes for a much more robust eco-system and cheaper handling of resources by intermediary systems. Some ecosystems restrict distribution of resources to only those systems that do fully understand the resources, and as a consequence implementers may believe that the narrative is superfluous. However experience shows that such eco-systems often open up to new participants over time." + } + ], + "key": "dom-6", + "severity": "warning", + "human": "A resource should have narrative for robust management", + "expression": "text.`div`.exists()", + "xpath": "exists(f:text/h:div)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-5", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a security label", + "expression": "contained.meta.security.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:security))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + } + ], + "mustSupport": false, + "isModifier": false, + "mapping": [ + { + "identity": "rim", + "map": "Entity. Role, or Act" + }, + { + "identity": "rim", + "map": "Patient[classCode=PAT]" + }, + { + "identity": "cda", + "map": "ClinicalDocument.recordTarget.patientRole" + }, + { + "identity": "w5", + "map": "administrative.individual" + } + ] + }, + { + "id": "Patient.id", + "path": "Patient.id", + "short": "Logical id of this artifact", + "definition": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "comment": "The only time that a resource does not have an id is when it is being submitted to the server using a create operation.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "id" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true + }, + { + "id": "Patient.meta", + "extension": [ + { "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.meta", + "short": "Metadata about the resource", + "definition": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.meta", + "min": 0, + "max": "1" }, - { + "type": [ + { + "code": "Meta" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.implicitRules", + "path": "Patient.implicitRules", + "short": "A set of rules under which this content was created", + "definition": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "comment": "Asserting this rule set restricts the content to be only understood by a limited set of trading partners. This inherently limits the usefulness of the data in the long term. However, the existing health eco-system is highly fractured, and not yet ready to define, collect, and exchange data in a generally computable sense. Wherever possible, implementers and/or specification writers should avoid using this element. Often, when used, the URL is a reference to an implementation guide that defines these special rules as part of it's narrative along with other profiles, value sets, etc.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.implicitRules", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "uri" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because the implicit rules may provide additional knowledge about the resource that modifies it's meaning or interpretation", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.language", + "path": "Patient.language", + "short": "Language of the resource content", + "definition": "The base language in which the resource is written.", + "comment": "Language is provided to support indexing and accessibility (typically, services such as text to speech use the language tag). The html language tag in the narrative applies to the narrative. The language tag on the resource may be used to specify the language of other presentations generated from the data in the resource. Not all the content has to be in the base language. The Resource.language should not be assumed to apply to the narrative automatically. If a language is specified, it should it also be specified on the div element in the html (see rules in HTML5 for information about the relationship between xml:lang and the html lang attribute).", + "min": 0, + "max": "1", + "base": { + "path": "Resource.language", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.text", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", "valueCode": "4.0.0" + } + ], + "path": "Patient.text", + "short": "Text summary of the resource, for human interpretation", + "definition": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "comment": "Contained resources do not have narrative. Resources that are not contained SHOULD have a narrative. In some cases, a resource may only have text with little or no additional discrete data (as long as all minOccurs=1 elements are satisfied). This may be necessary for data from legacy systems where information is captured as a \"text blob\" or where text is additionally entered raw or narrated and encoded information is added later.", + "alias": [ + "narrative", + "html", + "xhtml", + "display" + ], + "min": 0, + "max": "1", + "base": { + "path": "DomainResource.text", + "min": 0, + "max": "1" }, - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm", - "valueInteger": 5 + "type": [ + { + "code": "Narrative" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + }, + { + "identity": "rim", + "map": "Act.text?" + } + ] + }, + { + "id": "Patient.contained", + "path": "Patient.contained", + "short": "Contained, inline Resources", + "definition": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, and nor can they have their own independent transaction scope.", + "comment": "This should never be done when the content can be identified properly, as once identification is lost, it is extremely difficult (and context dependent) to restore it again. Contained resources may have profiles and tags In their meta elements, but SHALL NOT have security labels.", + "alias": [ + "inline resources", + "anonymous resources", + "contained resources" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.contained", + "min": 0, + "max": "*" }, - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-security-category", - "valueCode": "patient" + "type": [ + { + "code": "Resource" + } + ], + "constraint": [ + { + "key": "dom-r4b", + "severity": "warning", + "human": "Containing new R4B resources within R4 resources may cause interoperability issues if instances are shared with R4 systems", + "expression": "($this is Citation or $this is Evidence or $this is EvidenceReport or $this is EvidenceVariable or $this is MedicinalProductDefinition or $this is PackagedProductDefinition or $this is AdministrableProductDefinition or $this is Ingredient or $this is ClinicalUseDefinition or $this is RegulatedAuthorization or $this is SubstanceDefinition or $this is SubscriptionStatus or $this is SubscriptionTopic) implies (%resource is Citation or %resource is Evidence or %resource is EvidenceReport or %resource is EvidenceVariable or %resource is MedicinalProductDefinition or %resource is PackagedProductDefinition or %resource is AdministrableProductDefinition or %resource is Ingredient or %resource is ClinicalUseDefinition or %resource is RegulatedAuthorization or %resource is SubstanceDefinition or %resource is SubscriptionStatus or %resource is SubscriptionTopic)", + "xpath": "not(f:Citation|f:Evidence|f:EvidenceReport|f:EvidenceVariable|f:MedicinalProductDefinition|f:PackagedProductDefinition|f:AdministrableProductDefinition|f:Ingredient|f:ClinicalUseDefinition|f:RegulatedAuthorization|f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic) or not(parent::f:Citation|parent::f:Evidence|parent::f:EvidenceReport|parent::f:EvidenceVariable|parent::f:MedicinalProductDefinition|parent::f:PackagedProductDefinition|parent::f:AdministrableProductDefinition|parent::f:Ingredient|parent::f:ClinicalUseDefinition|parent::f:RegulatedAuthorization|parent::f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Entity. Role, or Act" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.extension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.extension", + "slicing": { + "discriminator": [ + { + "type": "value", + "path": "url" + } + ], + "description": "Extensions are always sliced by (at least) url", + "rules": "open" }, - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg", - "valueCode": "pa" - } - ], - "url": "http://hl7.org/fhir/StructureDefinition/Patient", - "version": "4.3.0", - "name": "Patient", - "status": "active", - "experimental": false, - "date": "2022-05-28T12:47:40+10:00", - "publisher": "Health Level Seven International (Patient Administration)", - "contact": [ - { - "telecom": [ - { - "system": "url", - "value": "http://hl7.org/fhir" - } - ] + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.extension", + "min": 0, + "max": "*" }, - { - "telecom": [ - { - "system": "url", - "value": "http://www.hl7.org/Special/committees/pafm/index.cfm" - } - ] - } - ], - "description": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", - "purpose": "Tracking patient is the center of the healthcare process.", - "fhirVersion": "4.3.0", - "mapping": [ - { + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.modifierExtension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.modifierExtension", + "slicing": { + "discriminator": [ + { + "type": "value", + "path": "url" + } + ], + "description": "Extensions are always sliced by (at least) url", + "rules": "open" + }, + "short": "Extensions that cannot be ignored", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the resource that contains them", + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { "identity": "rim", - "uri": "http://hl7.org/v3", - "name": "RIM Mapping" + "map": "N/A" + } + ] + }, + { + "id": "Patient.identifier", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.identifier", + "short": "An identifier for this patient", + "definition": "An identifier for this patient.", + "requirements": "Patients are almost always assigned specific numerical identifiers.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.identifier" }, - { + "type": [ + { + "code": "Identifier" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "CX / EI (occasionally, more often EI maps to a resource id or a URL)" + }, + { + "identity": "rim", + "map": "II - The Identifier class is a little looser than the v3 type II because it allows URIs as well as registered OIDs or GUIDs. Also maps to Role[classCode=IDENT]" + }, + { + "identity": "servd", + "map": "Identifier" + }, + { + "identity": "w5", + "map": "FiveWs.identifier" + }, + { + "identity": "v2", + "map": "PID-3" + }, + { + "identity": "rim", + "map": "id" + }, + { "identity": "cda", - "uri": "http://hl7.org/v3/cda", - "name": "CDA (R2)" + "map": ".id" + } + ] + }, + { + "id": "Patient.active", + "path": "Patient.active", + "short": "Whether this patient's record is in active use", + "definition": "Whether this patient record is in active use. \nMany systems use this property to mark as non-current patients, such as those that have not been seen for a period of time based on an organization's business rules.\n\nIt is often used to filter patient lists to exclude inactive patients\n\nDeceased patients may also be marked as inactive for the same reasons, but may be active for some time after death.", + "comment": "If a record is inactive, and linked to an active record, then future patient/record updates should occur on the other patient.", + "requirements": "Need to be able to mark a patient record as not to be used because it was created in error.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.active", + "max": "1" }, - { + "type": [ + { + "code": "boolean" + } + ], + "meaningWhenMissing": "This resource is generally assumed to be active if no value is provided for the active element", + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labelled as a modifier because it is a status element that can indicate that a record should not be treated as valid", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { "identity": "w5", - "uri": "http://hl7.org/fhir/fivews", - "name": "FiveWs Pattern Mapping" + "map": "FiveWs.status" + }, + { + "identity": "rim", + "map": "statusCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.name", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.name", + "short": "A name associated with the patient", + "definition": "A name associated with the individual.", + "comment": "A patient may have multiple names with different uses or applicable periods. For animals, the name is a \"HumanName\" in the sense that is assigned and used by humans and has the same patterns.", + "requirements": "Need to be able to track the patient by multiple names. Examples are your official name and a partner name.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.name" }, - { + "type": [ + { + "code": "HumanName" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "XPN" + }, + { + "identity": "rim", + "map": "EN (actually, PN)" + }, + { + "identity": "servd", + "map": "ProviderName" + }, + { "identity": "v2", - "uri": "http://hl7.org/v2", - "name": "HL7 v2 Mapping" + "map": "PID-5, PID-9" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": ".patient.name" + } + ] + }, + { + "id": "Patient.telecom", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.telecom", + "short": "A contact detail for the individual", + "definition": "A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted.", + "comment": "A Patient may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently and also to help with identification. The address might not go directly to the individual, but may reach another party that is able to proxy for the patient (i.e. home phone, or pet owner's phone).", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.telecom" }, - { + "type": [ + { + "code": "ContactPoint" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "cpt-2", + "severity": "error", + "human": "A system is required if a value is provided.", + "expression": "value.empty() or system.exists()", + "xpath": "not(exists(f:value)) or exists(f:system)", + "source": "http://hl7.org/fhir/StructureDefinition/ContactPoint" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "XTN" + }, + { + "identity": "rim", + "map": "TEL" + }, + { + "identity": "servd", + "map": "ContactPoint" + }, + { + "identity": "v2", + "map": "PID-13, PID-14, PID-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": ".telecom" + } + ] + }, + { + "id": "Patient.gender", + "path": "Patient.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes.", + "comment": "The gender might not match the biological sex as determined by genetics or the individual's preferred identification. Note that for both humans and particularly animals, there are other legitimate possibilities than male and female, though the vast majority of systems and contexts only support male and female. Systems providing decision support or enforcing business rules should ideally do this on the basis of Observations dealing with the specific sex or gender aspect of interest (anatomical, chromosomal, social, etc.) However, because these observations are infrequently recorded, defaulting to the administrative gender is common practice. Where such defaulting occurs, rule enforcement should allow for the variation between administrative and biological, chromosomal and other gender aspects. For example, an alert about a hysterectomy on a male should be handled as a warning or overridable error, not a \"hard\" error. See the Patient Gender and Sex section for additional information about communicating patient gender and sex.", + "requirements": "Needed for identification of the individual, in combination with (at least) name and birth date.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.gender", + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "PID-8" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": ".patient.administrativeGenderCode" + } + ] + }, + { + "id": "Patient.birthDate", + "path": "Patient.birthDate", + "short": "The date of birth for the individual", + "definition": "The date of birth for the individual.", + "comment": "At least an estimated year should be provided as a guess if the real DOB is unknown There is a standard extension \"patient-birthTime\" available that should be used where Time is required (such as in maternity/infant care systems).", + "requirements": "Age of the individual drives many clinical processes.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.birthDate", + "max": "1" + }, + "type": [ + { + "code": "date" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "PID-7" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/birthTime" + }, + { + "identity": "cda", + "map": ".patient.birthTime" + }, + { "identity": "loinc", - "uri": "http://loinc.org", - "name": "LOINC code for the element" - } - ], - "kind": "resource", - "abstract": false, - "type": "Patient", - "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", - "derivation": "specialization", - "snapshot": { - "element": [ - { - "id": "Patient", - "path": "Patient", - "short": "Information about an individual or animal receiving health care services", - "definition": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", - "alias": [ "SubjectOfCare Client Resident" ], - "min": 0, - "max": "*", - "base": { - "path": "Patient", - "min": 0, - "max": "*" - }, - "constraint": [ - { - "key": "dom-2", - "severity": "error", - "human": "If the resource is contained in another resource, it SHALL NOT contain nested Resources", - "expression": "contained.contained.empty()", - "xpath": "not(parent::f:contained and f:contained)", - "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" - }, - { - "key": "dom-3", - "severity": "error", - "human": "If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource", - "expression": "contained.where(((id.exists() and ('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url)))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(uri) = '#').exists()).not()).trace('unmatched', id).empty()", - "xpath": "not(exists(for $contained in f:contained return $contained[not(exists(parent::*/descendant::f:reference/@value=concat('#', $contained/*/f:id/@value)) or exists(descendant::f:reference[@value='#']))]))", - "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" - }, - { - "key": "dom-4", - "severity": "error", - "human": "If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated", - "expression": "contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()", - "xpath": "not(exists(f:contained/*/f:meta/f:versionId)) and not(exists(f:contained/*/f:meta/f:lastUpdated))", - "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" - }, - { - "key": "dom-5", - "severity": "error", - "human": "If a resource is contained in another resource, it SHALL NOT have a security label", - "expression": "contained.meta.security.empty()", - "xpath": "not(exists(f:contained/*/f:meta/f:security))", - "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" - }, - { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice", - "valueBoolean": true - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation", - "valueMarkdown": "When a resource has no narrative, only systems that fully understand the data can display the resource to a human safely. Including a human readable representation in the resource makes for a much more robust eco-system and cheaper handling of resources by intermediary systems. Some ecosystems restrict distribution of resources to only those systems that do fully understand the resources, and as a consequence implementers may believe that the narrative is superfluous. However experience shows that such eco-systems often open up to new participants over time." - } - ], - "key": "dom-6", - "severity": "warning", - "human": "A resource should have narrative for robust management", - "expression": "text.`div`.exists()", - "xpath": "exists(f:text/h:div)", - "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "Entity. Role, or Act" - }, - { - "identity": "rim", - "map": "Patient[classCode=PAT]" - }, - { - "identity": "cda", - "map": "ClinicalDocument.recordTarget.patientRole" - }, - { - "identity": "w5", - "map": "administrative.individual" - } - ] - }, - { - "id": "Patient.id", - "path": "Patient.id", - "short": "Logical id of this artifact", - "definition": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", - "comment": "The only time that a resource does not have an id is when it is being submitted to the server using a create operation.", - "min": 0, - "max": "1", - "base": { - "path": "Resource.id", - "min": 0, - "max": "1" - }, - "type": [ - { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", - "valueUrl": "id" - } - ], - "code": "http://hl7.org/fhirpath/System.String" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true - }, - { - "id": "Patient.meta", - "path": "Patient.meta", - "short": "Metadata about the resource", - "definition": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", - "min": 0, - "max": "1", - "base": { - "path": "Resource.meta", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "Meta" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true - }, - { - "id": "Patient.implicitRules", - "path": "Patient.implicitRules", - "short": "A set of rules under which this content was created", - "definition": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", - "comment": "Asserting this rule set restricts the content to be only understood by a limited set of trading partners. This inherently limits the usefulness of the data in the long term. However, the existing health eco-system is highly fractured, and not yet ready to define, collect, and exchange data in a generally computable sense. Wherever possible, implementers and/or specification writers should avoid using this element. Often, when used, the URL is a reference to an implementation guide that defines these special rules as part of it's narrative along with other profiles, value sets, etc.", - "min": 0, - "max": "1", - "base": { - "path": "Resource.implicitRules", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "uri" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": true, - "isModifierReason": "This element is labeled as a modifier because the implicit rules may provide additional knowledge about the resource that modifies it's meaning or interpretation", - "isSummary": true - }, - { - "id": "Patient.language", - "path": "Patient.language", - "short": "Language of the resource content", - "definition": "The base language in which the resource is written.", - "comment": "Language is provided to support indexing and accessibility (typically, services such as text to speech use the language tag). The html language tag in the narrative applies to the narrative. The language tag on the resource may be used to specify the language of other presentations generated from the data in the resource. Not all the content has to be in the base language. The Resource.language should not be assumed to apply to the narrative automatically. If a language is specified, it should it also be specified on the div element in the html (see rules in HTML5 for information about the relationship between xml:lang and the html lang attribute).", - "min": 0, - "max": "1", - "base": { - "path": "Resource.language", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "code" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", - "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "Language" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", - "valueBoolean": true - } - ], - "strength": "preferred", - "description": "IETF language tag", - "valueSet": "http://hl7.org/fhir/ValueSet/languages" - } - }, - { - "id": "Patient.text", - "path": "Patient.text", - "short": "Text summary of the resource, for human interpretation", - "definition": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", - "comment": "Contained resources do not have narrative. Resources that are not contained SHOULD have a narrative. In some cases, a resource may only have text with little or no additional discrete data (as long as all minOccurs=1 elements are satisfied). This may be necessary for data from legacy systems where information is captured as a \"text blob\" or where text is additionally entered raw or narrated and encoded information is added later.", - "alias": [ - "narrative", - "html", - "xhtml", - "display" - ], - "min": 0, - "max": "1", - "base": { - "path": "DomainResource.text", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "Narrative" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "Act.text?" - } - ] - }, - { - "id": "Patient.contained", - "path": "Patient.contained", - "short": "Contained, inline Resources", - "definition": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, and nor can they have their own independent transaction scope.", - "comment": "This should never be done when the content can be identified properly, as once identification is lost, it is extremely difficult (and context dependent) to restore it again. Contained resources may have profiles and tags In their meta elements, but SHALL NOT have security labels.", - "alias": [ - "inline resources", - "anonymous resources", - "contained resources" - ], - "min": 0, - "max": "*", - "base": { - "path": "DomainResource.contained", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Resource" - } - ], - "constraint": [ - { - "key": "dom-r4b", - "severity": "warning", - "human": "Containing new R4B resources within R4 resources may cause interoperability issues if instances are shared with R4 systems", - "expression": "($this is Citation or $this is Evidence or $this is EvidenceReport or $this is EvidenceVariable or $this is MedicinalProductDefinition or $this is PackagedProductDefinition or $this is AdministrableProductDefinition or $this is Ingredient or $this is ClinicalUseDefinition or $this is RegulatedAuthorization or $this is SubstanceDefinition or $this is SubscriptionStatus or $this is SubscriptionTopic) implies (%resource is Citation or %resource is Evidence or %resource is EvidenceReport or %resource is EvidenceVariable or %resource is MedicinalProductDefinition or %resource is PackagedProductDefinition or %resource is AdministrableProductDefinition or %resource is Ingredient or %resource is ClinicalUseDefinition or %resource is RegulatedAuthorization or %resource is SubstanceDefinition or %resource is SubscriptionStatus or %resource is SubscriptionTopic)", - "xpath": "not(f:Citation|f:Evidence|f:EvidenceReport|f:EvidenceVariable|f:MedicinalProductDefinition|f:PackagedProductDefinition|f:AdministrableProductDefinition|f:Ingredient|f:ClinicalUseDefinition|f:RegulatedAuthorization|f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic) or not(parent::f:Citation|parent::f:Evidence|parent::f:EvidenceReport|parent::f:EvidenceVariable|parent::f:MedicinalProductDefinition|parent::f:PackagedProductDefinition|parent::f:AdministrableProductDefinition|parent::f:Ingredient|parent::f:ClinicalUseDefinition|parent::f:RegulatedAuthorization|parent::f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic)", - "source": "http://hl7.org/fhir/StructureDefinition/Patient" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "N/A" - } - ] - }, - { - "id": "Patient.extension", - "path": "Patient.extension", - "short": "Additional content defined by implementations", - "definition": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", - "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", - "alias": [ - "extensions", - "user content" - ], - "min": 0, - "max": "*", - "base": { - "path": "DomainResource.extension", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Extension" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - }, - { - "key": "ext-1", - "severity": "error", - "human": "Must have either extensions or value[x], not both", - "expression": "extension.exists() != value.exists()", - "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", - "source": "http://hl7.org/fhir/StructureDefinition/Extension" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "N/A" - } - ] - }, - { - "id": "Patient.modifierExtension", - "path": "Patient.modifierExtension", - "short": "Extensions that cannot be ignored", - "definition": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", - "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", - "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", - "alias": [ - "extensions", - "user content" - ], - "min": 0, - "max": "*", - "base": { - "path": "DomainResource.modifierExtension", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Extension" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - }, - { - "key": "ext-1", - "severity": "error", - "human": "Must have either extensions or value[x], not both", - "expression": "extension.exists() != value.exists()", - "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", - "source": "http://hl7.org/fhir/StructureDefinition/Extension" - } - ], - "mustSupport": false, - "isModifier": true, - "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the resource that contains them", - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "N/A" - } - ] - }, - { - "id": "Patient.identifier", - "path": "Patient.identifier", - "short": "An identifier for this patient", - "definition": "An identifier for this patient.", - "requirements": "Patients are almost always assigned specific numerical identifiers.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.identifier", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Identifier" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "w5", - "map": "FiveWs.identifier" - }, - { - "identity": "v2", - "map": "PID-3" - }, - { - "identity": "rim", - "map": "id" - }, - { - "identity": "cda", - "map": ".id" - } - ] - }, - { - "id": "Patient.active", - "path": "Patient.active", - "short": "Whether this patient's record is in active use", - "definition": "Whether this patient record is in active use. \nMany systems use this property to mark as non-current patients, such as those that have not been seen for a period of time based on an organization's business rules.\n\nIt is often used to filter patient lists to exclude inactive patients\n\nDeceased patients may also be marked as inactive for the same reasons, but may be active for some time after death.", - "comment": "If a record is inactive, and linked to an active record, then future patient/record updates should occur on the other patient.", - "requirements": "Need to be able to mark a patient record as not to be used because it was created in error.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.active", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "boolean" - } - ], - "meaningWhenMissing": "This resource is generally assumed to be active if no value is provided for the active element", - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": true, - "isModifierReason": "This element is labelled as a modifier because it is a status element that can indicate that a record should not be treated as valid", - "isSummary": true, - "mapping": [ - { - "identity": "w5", - "map": "FiveWs.status" - }, - { - "identity": "rim", - "map": "statusCode" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.name", - "path": "Patient.name", - "short": "A name associated with the patient", - "definition": "A name associated with the individual.", - "comment": "A patient may have multiple names with different uses or applicable periods. For animals, the name is a \"HumanName\" in the sense that is assigned and used by humans and has the same patterns.", - "requirements": "Need to be able to track the patient by multiple names. Examples are your official name and a partner name.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.name", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "HumanName" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-5, PID-9" - }, - { - "identity": "rim", - "map": "name" - }, - { - "identity": "cda", - "map": ".patient.name" - } - ] - }, - { - "id": "Patient.telecom", - "path": "Patient.telecom", - "short": "A contact detail for the individual", - "definition": "A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted.", - "comment": "A Patient may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently and also to help with identification. The address might not go directly to the individual, but may reach another party that is able to proxy for the patient (i.e. home phone, or pet owner's phone).", - "requirements": "People have (primary) ways to contact them in some way such as phone, email.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.telecom", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "ContactPoint" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-13, PID-14, PID-40" - }, - { - "identity": "rim", - "map": "telecom" - }, - { - "identity": "cda", - "map": ".telecom" - } - ] - }, - { - "id": "Patient.gender", - "path": "Patient.gender", - "short": "male | female | other | unknown", - "definition": "Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes.", - "comment": "The gender might not match the biological sex as determined by genetics or the individual's preferred identification. Note that for both humans and particularly animals, there are other legitimate possibilities than male and female, though the vast majority of systems and contexts only support male and female. Systems providing decision support or enforcing business rules should ideally do this on the basis of Observations dealing with the specific sex or gender aspect of interest (anatomical, chromosomal, social, etc.) However, because these observations are infrequently recorded, defaulting to the administrative gender is common practice. Where such defaulting occurs, rule enforcement should allow for the variation between administrative and biological, chromosomal and other gender aspects. For example, an alert about a hysterectomy on a male should be handled as a warning or overridable error, not a \"hard\" error. See the Patient Gender and Sex section for additional information about communicating patient gender and sex.", - "requirements": "Needed for identification of the individual, in combination with (at least) name and birth date.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.gender", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "code" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "AdministrativeGender" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", - "valueBoolean": true - } - ], - "strength": "required", - "description": "The gender of a person used for administrative purposes.", - "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" - }, - "mapping": [ - { - "identity": "v2", - "map": "PID-8" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" - }, - { - "identity": "cda", - "map": ".patient.administrativeGenderCode" - } - ] - }, - { - "id": "Patient.birthDate", - "path": "Patient.birthDate", - "short": "The date of birth for the individual", - "definition": "The date of birth for the individual.", - "comment": "At least an estimated year should be provided as a guess if the real DOB is unknown There is a standard extension \"patient-birthTime\" available that should be used where Time is required (such as in maternity/infant care systems).", - "requirements": "Age of the individual drives many clinical processes.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.birthDate", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "date" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-7" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/birthTime" - }, - { - "identity": "cda", - "map": ".patient.birthTime" - }, - { - "identity": "loinc", - "map": "21112-8" - } - ] - }, - { - "id": "Patient.deceased[x]", - "path": "Patient.deceased[x]", - "short": "Indicates if the individual is deceased or not", - "definition": "Indicates if the individual is deceased or not.", - "comment": "If there's no value in the instance, it means there is no statement on whether or not the individual is deceased. Most systems will interpret the absence of a value as a sign of the person being alive.", - "requirements": "The fact that a patient is deceased influences the clinical process. Also, in human communication and relation management it is necessary to know whether the person is alive.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.deceased[x]", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "boolean" - }, - { - "code": "dateTime" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": true, - "isModifierReason": "This element is labeled as a modifier because once a patient is marked as deceased, the actions that are appropriate to perform on the patient may be significantly different.", - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-30 (bool) and PID-29 (datetime)" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedTime" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.address", - "path": "Patient.address", - "short": "An address for the individual", - "definition": "An address for the individual.", - "comment": "Patient may have multiple addresses with different uses or applicable periods.", - "requirements": "May need to keep track of patient addresses for contacting, billing or reporting requirements and also to help with identification.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.address", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Address" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-11" - }, - { - "identity": "rim", - "map": "addr" - }, - { - "identity": "cda", - "map": ".addr" - } - ] - }, - { - "id": "Patient.maritalStatus", - "path": "Patient.maritalStatus", - "short": "Marital (civil) status of a patient", - "definition": "This field contains a patient's most recent marital (civil) status.", - "requirements": "Most, if not all systems capture it.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.maritalStatus", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "CodeableConcept" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "MaritalStatus" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", - "valueBoolean": true - } - ], - "strength": "extensible", - "description": "The domestic partnership status of a person.", - "valueSet": "http://hl7.org/fhir/ValueSet/marital-status" - }, - "mapping": [ - { - "identity": "v2", - "map": "PID-16" - }, - { - "identity": "rim", - "map": "player[classCode=PSN]/maritalStatusCode" - }, - { - "identity": "cda", - "map": ".patient.maritalStatusCode" - } - ] - }, - { - "id": "Patient.multipleBirth[x]", - "path": "Patient.multipleBirth[x]", - "short": "Whether patient is part of a multiple birth", - "definition": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", - "comment": "Where the valueInteger is provided, the number is the birth number in the sequence. E.g. The middle birth in triplets would be valueInteger=2 and the third born would have valueInteger=3 If a boolean value was provided for this triplets example, then all 3 patient records would have valueBoolean=true (the ordering is not indicated).", - "requirements": "For disambiguation of multiple-birth children, especially relevant where the care provider doesn't meet the patient, such as labs.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.multipleBirth[x]", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "boolean" - }, - { - "code": "integer" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "PID-24 (bool), PID-25 (integer)" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthOrderNumber" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.photo", - "path": "Patient.photo", - "short": "Image of the patient", - "definition": "Image of the patient.", - "comment": "Guidelines:\n* Use id photos, not clinical photos.\n* Limit dimensions to thumbnail.\n* Keep byte count low to ease resource updates.", - "requirements": "Many EHR systems have the capability to capture an image of the patient. Fits with newer social media usage too.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.photo", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Attachment" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "OBX-5 - needs a profile" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/desc" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact", - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name", - "valueString": "Contact" - } - ], - "path": "Patient.contact", - "short": "A contact party (e.g. guardian, partner, friend) for the patient", - "definition": "A contact party (e.g. guardian, partner, friend) for the patient.", - "comment": "Contact covers all kinds of contact parties: family members, business contacts, guardians, caregivers. Not applicable to register pedigree and family ties beyond use of having contact.", - "requirements": "Need to track people you can contact about the patient.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.contact", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "BackboneElement" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", - "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", - "xpath": "@value|f:*|h:div|self::f:Parameters", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - }, - { - "key": "pat-1", - "severity": "error", - "human": "SHALL at least contain a contact's details or a reference to an organization", - "expression": "name.exists() or telecom.exists() or address.exists() or organization.exists()", - "xpath": "exists(f:name) or exists(f:telecom) or exists(f:address) or exists(f:organization)", - "source": "http://hl7.org/fhir/StructureDefinition/Patient" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/scopedRole[classCode=CON]" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.id", - "path": "Patient.contact.id", - "representation": [ "xmlAttr" ], - "short": "Unique id for inter-element referencing", - "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", - "min": 0, - "max": "1", - "base": { - "path": "Element.id", - "min": 0, - "max": "1" - }, - "type": [ - { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", - "valueUrl": "string" - } - ], - "code": "http://hl7.org/fhirpath/System.String" - } - ], - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.extension", - "path": "Patient.contact.extension", - "short": "Additional content defined by implementations", - "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", - "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", - "alias": [ - "extensions", - "user content" - ], - "min": 0, - "max": "*", - "base": { - "path": "Element.extension", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Extension" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - }, - { - "key": "ext-1", - "severity": "error", - "human": "Must have either extensions or value[x], not both", - "expression": "extension.exists() != value.exists()", - "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", - "source": "http://hl7.org/fhir/StructureDefinition/Extension" - } - ], - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.modifierExtension", - "path": "Patient.contact.modifierExtension", - "short": "Extensions that cannot be ignored even if unrecognized", - "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", - "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", - "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", - "alias": [ - "extensions", - "user content", - "modifiers" - ], - "min": 0, - "max": "*", - "base": { - "path": "BackboneElement.modifierExtension", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Extension" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - }, - { - "key": "ext-1", - "severity": "error", - "human": "Must have either extensions or value[x], not both", - "expression": "extension.exists() != value.exists()", - "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", - "source": "http://hl7.org/fhir/StructureDefinition/Extension" - } - ], - "isModifier": true, - "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", - "isSummary": true, - "mapping": [ - { - "identity": "rim", - "map": "N/A" - } - ] - }, - { - "id": "Patient.contact.relationship", - "path": "Patient.contact.relationship", - "short": "The kind of relationship", - "definition": "The nature of the relationship between the patient and the contact person.", - "requirements": "Used to determine which contact person is the most relevant to approach, depending on circumstances.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.contact.relationship", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "CodeableConcept" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "ContactRelationship" - } - ], - "strength": "extensible", - "description": "The nature of the relationship between a patient and a contact person for that patient.", - "valueSet": "http://hl7.org/fhir/ValueSet/patient-contactrelationship" - }, - "mapping": [ - { - "identity": "v2", - "map": "NK1-7, NK1-3" - }, - { - "identity": "rim", - "map": "code" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.name", - "path": "Patient.contact.name", - "short": "A name associated with the contact person", - "definition": "A name associated with the contact person.", - "requirements": "Contact persons need to be identified by name, but it is uncommon to need details about multiple other names for that contact person.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.contact.name", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "HumanName" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "NK1-2" - }, - { - "identity": "rim", - "map": "name" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.telecom", - "path": "Patient.contact.telecom", - "short": "A contact detail for the person", - "definition": "A contact detail for the person, e.g. a telephone number or an email address.", - "comment": "Contact may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently, and also to help with identification.", - "requirements": "People have (primary) ways to contact them in some way such as phone, email.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.contact.telecom", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "ContactPoint" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "NK1-5, NK1-6, NK1-40" - }, - { - "identity": "rim", - "map": "telecom" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.address", - "path": "Patient.contact.address", - "short": "Address for the contact person", - "definition": "Address for the contact person.", - "requirements": "Need to keep track where the contact person can be contacted per postal mail or visited.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.contact.address", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "Address" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "NK1-4" - }, - { - "identity": "rim", - "map": "addr" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.gender", - "path": "Patient.contact.gender", - "short": "male | female | other | unknown", - "definition": "Administrative Gender - the gender that the contact person is considered to have for administration and record keeping purposes.", - "requirements": "Needed to address the person correctly.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.contact.gender", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "code" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "AdministrativeGender" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", - "valueBoolean": true - } - ], - "strength": "required", - "description": "The gender of a person used for administrative purposes.", - "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" - }, - "mapping": [ - { - "identity": "v2", - "map": "NK1-15" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.organization", - "path": "Patient.contact.organization", - "short": "Organization that is associated with the contact", - "definition": "Organization on behalf of which the contact is acting or for which the contact is working.", - "requirements": "For guardians or business related contacts, the organization is relevant.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.contact.organization", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "Reference", - "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] - } - ], - "condition": [ "pat-1" ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "NK1-13, NK1-30, NK1-31, NK1-32, NK1-41" - }, - { - "identity": "rim", - "map": "scoper" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.period", - "path": "Patient.contact.period", - "short": "The period during which this contact person or organization is valid to be contacted relating to this patient", - "definition": "The period during which this contact person or organization is valid to be contacted relating to this patient.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.contact.period", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "Period" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "effectiveTime" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.communication", - "path": "Patient.communication", - "short": "A language which may be used to communicate with the patient about his or her health", - "definition": "A language which may be used to communicate with the patient about his or her health.", - "comment": "If no language is specified, this *implies* that the default local language is spoken. If you need to convey proficiency for multiple modes, then you need multiple Patient.Communication associations. For animals, language is not a relevant field, and should be absent from the instance. If the Patient does not speak the default local language, then the Interpreter Required Standard can be used to explicitly declare that an interpreter is required.", - "requirements": "If a patient does not speak the local language, interpreters may be required, so languages spoken and proficiency are important things to keep track of both for patient and other persons of interest.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.communication", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "BackboneElement" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", - "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", - "xpath": "@value|f:*|h:div|self::f:Parameters", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "LanguageCommunication" - }, - { - "identity": "cda", - "map": "patient.languageCommunication" - } - ] - }, - { - "id": "Patient.communication.id", - "path": "Patient.communication.id", - "representation": [ "xmlAttr" ], - "short": "Unique id for inter-element referencing", - "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", - "min": 0, - "max": "1", - "base": { - "path": "Element.id", - "min": 0, - "max": "1" - }, - "type": [ - { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", - "valueUrl": "string" - } - ], - "code": "http://hl7.org/fhirpath/System.String" - } - ], - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "n/a" - } - ] - }, - { - "id": "Patient.communication.extension", - "path": "Patient.communication.extension", - "short": "Additional content defined by implementations", - "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", - "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", - "alias": [ - "extensions", - "user content" - ], - "min": 0, - "max": "*", - "base": { - "path": "Element.extension", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Extension" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - }, - { - "key": "ext-1", - "severity": "error", - "human": "Must have either extensions or value[x], not both", - "expression": "extension.exists() != value.exists()", - "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", - "source": "http://hl7.org/fhir/StructureDefinition/Extension" - } - ], - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "n/a" - } - ] - }, - { - "id": "Patient.communication.modifierExtension", - "path": "Patient.communication.modifierExtension", - "short": "Extensions that cannot be ignored even if unrecognized", - "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", - "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", - "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", - "alias": [ - "extensions", - "user content", - "modifiers" - ], - "min": 0, - "max": "*", - "base": { - "path": "BackboneElement.modifierExtension", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Extension" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - }, - { - "key": "ext-1", - "severity": "error", - "human": "Must have either extensions or value[x], not both", - "expression": "extension.exists() != value.exists()", - "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", - "source": "http://hl7.org/fhir/StructureDefinition/Extension" - } - ], - "isModifier": true, - "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", - "isSummary": true, - "mapping": [ - { - "identity": "rim", - "map": "N/A" - } - ] - }, - { - "id": "Patient.communication.language", - "path": "Patient.communication.language", - "short": "The language which can be used to communicate with the patient about his or her health", - "definition": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-EN\" for England English.", - "comment": "The structure aa-BB with this exact casing is one the most widely used notations for locale. However not all systems actually code this but instead have it as free text. Hence CodeableConcept instead of code as the data type.", - "requirements": "Most systems in multilingual countries will want to convey language. Not all systems actually need the regional dialect.", - "min": 1, - "max": "1", - "base": { - "path": "Patient.communication.language", - "min": 1, - "max": "1" - }, - "type": [ - { - "code": "CodeableConcept" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", - "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "Language" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", - "valueBoolean": true - } - ], - "strength": "preferred", - "description": "IETF language tag", - "valueSet": "http://hl7.org/fhir/ValueSet/languages" - }, - "mapping": [ - { - "identity": "v2", - "map": "PID-15, LAN-2" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/languageCommunication/code" - }, - { - "identity": "cda", - "map": ".languageCode" - } - ] - }, - { - "id": "Patient.communication.preferred", - "path": "Patient.communication.preferred", - "short": "Language preference indicator", - "definition": "Indicates whether or not the patient prefers this language (over other languages he masters up a certain level).", - "comment": "This language is specifically identified for communicating healthcare information.", - "requirements": "People that master multiple languages up to certain level may prefer one or more, i.e. feel more confident in communicating in a particular language making other languages sort of a fall back method.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.communication.preferred", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "boolean" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "PID-15" - }, - { - "identity": "rim", - "map": "preferenceInd" - }, - { - "identity": "cda", - "map": ".preferenceInd" - } - ] - }, - { - "id": "Patient.generalPractitioner", - "path": "Patient.generalPractitioner", - "short": "Patient's nominated primary care provider", - "definition": "Patient's nominated care provider.", - "comment": "This may be the primary care provider (in a GP context), or it may be a patient nominated care manager in a community/disability setting, or even organization that will provide people to perform the care provider roles. It is not to be used to record Care Teams, these should be in a CareTeam resource that may be linked to the CarePlan or EpisodeOfCare resources.\nMultiple GPs may be recorded against the patient for various reasons, such as a student that has his home GP listed along with the GP at university during the school semesters, or a \"fly-in/fly-out\" worker that has the onsite GP also included with his home GP to remain aware of medical issues.\n\nJurisdictions may decide that they can profile this down to 1 if desired, or 1 per type.", - "alias": [ "careProvider" ], - "min": 0, - "max": "*", - "base": { - "path": "Patient.generalPractitioner", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Reference", - "targetProfile": [ - "http://hl7.org/fhir/StructureDefinition/Organization", - "http://hl7.org/fhir/StructureDefinition/Practitioner", - "http://hl7.org/fhir/StructureDefinition/PractitionerRole" - ] - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "PD1-4" - }, - { - "identity": "rim", - "map": "subjectOf.CareEvent.performer.AssignedEntity" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.managingOrganization", - "path": "Patient.managingOrganization", - "short": "Organization that is the custodian of the patient record", - "definition": "Organization that is the custodian of the patient record.", - "comment": "There is only one managing organization for a specific patient record. Other organizations will have their own Patient record, and may use the Link property to join the records together (or a Person resource which can include confidence ratings for the association).", - "requirements": "Need to know who recognizes this patient record, manages and updates it.", - "min": 0, - "max": "1", - "base": { - "path": "Patient.managingOrganization", - "min": 0, - "max": "1" - }, - "type": [ - { - "code": "Reference", - "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "rim", - "map": "scoper" - }, - { - "identity": "cda", - "map": ".providerOrganization" - } - ] - }, - { - "id": "Patient.link", - "path": "Patient.link", - "short": "Link to another patient resource that concerns the same actual person", - "definition": "Link to another patient resource that concerns the same actual patient.", - "comment": "There is no assumption that linked patient records have mutual links.", - "requirements": "There are multiple use cases: \n\n* Duplicate patient records due to the clerical errors associated with the difficulties of identifying humans consistently, and \n* Distribution of patient information across multiple servers.", - "min": 0, - "max": "*", - "base": { - "path": "Patient.link", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "BackboneElement" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", - "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", - "xpath": "@value|f:*|h:div|self::f:Parameters", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": true, - "isModifierReason": "This element is labeled as a modifier because it might not be the main Patient resource, and the referenced patient should be used instead of this Patient record. This is when the link.type value is 'replaced-by'", - "isSummary": true, - "mapping": [ - { - "identity": "rim", - "map": "outboundLink" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.link.id", - "path": "Patient.link.id", - "representation": [ "xmlAttr" ], - "short": "Unique id for inter-element referencing", - "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", - "min": 0, - "max": "1", - "base": { - "path": "Element.id", - "min": 0, - "max": "1" - }, - "type": [ - { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", - "valueUrl": "string" - } - ], - "code": "http://hl7.org/fhirpath/System.String" - } - ], - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "n/a" - } - ] - }, - { - "id": "Patient.link.extension", - "path": "Patient.link.extension", - "short": "Additional content defined by implementations", - "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", - "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", - "alias": [ - "extensions", - "user content" - ], - "min": 0, - "max": "*", - "base": { - "path": "Element.extension", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Extension" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - }, - { - "key": "ext-1", - "severity": "error", - "human": "Must have either extensions or value[x], not both", - "expression": "extension.exists() != value.exists()", - "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", - "source": "http://hl7.org/fhir/StructureDefinition/Extension" - } - ], - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "n/a" - } - ] - }, - { - "id": "Patient.link.modifierExtension", - "path": "Patient.link.modifierExtension", - "short": "Extensions that cannot be ignored even if unrecognized", - "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", - "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", - "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", - "alias": [ - "extensions", - "user content", - "modifiers" - ], - "min": 0, - "max": "*", - "base": { - "path": "BackboneElement.modifierExtension", - "min": 0, - "max": "*" - }, - "type": [ - { - "code": "Extension" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - }, - { - "key": "ext-1", - "severity": "error", - "human": "Must have either extensions or value[x], not both", - "expression": "extension.exists() != value.exists()", - "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])", - "source": "http://hl7.org/fhir/StructureDefinition/Extension" - } - ], - "isModifier": true, - "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", - "isSummary": true, - "mapping": [ - { - "identity": "rim", - "map": "N/A" - } - ] - }, - { - "id": "Patient.link.other", - "path": "Patient.link.other", - "short": "The other patient or related person resource that the link refers to", - "definition": "The other patient resource that the link refers to.", - "comment": "Referencing a RelatedPerson here removes the need to use a Person record to associate a Patient and RelatedPerson as the same individual.", - "min": 1, - "max": "1", - "base": { - "path": "Patient.link.other", - "min": 1, - "max": "1" - }, - "type": [ - { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy", - "valueBoolean": false - } - ], - "code": "Reference", - "targetProfile": [ - "http://hl7.org/fhir/StructureDefinition/Patient", - "http://hl7.org/fhir/StructureDefinition/RelatedPerson" - ] - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-3, MRG-1" - }, - { - "identity": "rim", - "map": "id" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.link.type", - "path": "Patient.link.type", - "short": "replaced-by | replaces | refer | seealso", - "definition": "The type of link between this patient resource and another patient resource.", - "min": 1, - "max": "1", - "base": { - "path": "Patient.link.type", - "min": 1, - "max": "1" - }, - "type": [ - { - "code": "code" - } - ], - "constraint": [ - { - "key": "ele-1", - "severity": "error", - "human": "All FHIR elements must have a @value or children", - "expression": "hasValue() or (children().count() > id.count())", - "xpath": "@value|f:*|h:div", - "source": "http://hl7.org/fhir/StructureDefinition/Element" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "LinkType" - } - ], - "strength": "required", - "description": "The type of link between this patient resource and another patient resource.", - "valueSet": "http://hl7.org/fhir/ValueSet/link-type|4.3.0" - }, - "mapping": [ - { - "identity": "rim", - "map": "typeCode" - }, - { - "identity": "cda", - "map": "n/a" - } - ] + "map": "21112-8" + } + ] + }, + { + "id": "Patient.deceased[x]", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.deceased[x]", + "short": "Indicates if the individual is deceased or not", + "definition": "Indicates if the individual is deceased or not.", + "comment": "If there's no value in the instance, it means there is no statement on whether or not the individual is deceased. Most systems will interpret the absence of a value as a sign of the person being alive.", + "requirements": "The fact that a patient is deceased influences the clinical process. Also, in human communication and relation management it is necessary to know whether the person is alive.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.deceased[x]", + "max": "1" + }, + "type": [ + { + "code": "boolean" + }, + { + "code": "dateTime" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because once a patient is marked as deceased, the actions that are appropriate to perform on the patient may be significantly different.", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "PID-30 (bool) and PID-29 (datetime)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.address", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.address", + "short": "An address for the individual", + "definition": "An address for the individual.", + "comment": "Patient may have multiple addresses with different uses or applicable periods.", + "requirements": "May need to keep track of patient addresses for contacting, billing or reporting requirements and also to help with identification.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.address" + }, + "type": [ + { + "code": "Address" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "XAD" + }, + { + "identity": "rim", + "map": "AD" + }, + { + "identity": "servd", + "map": "Address" + }, + { + "identity": "v2", + "map": "PID-11" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": ".addr" + } + ] + }, + { + "id": "Patient.maritalStatus", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.maritalStatus", + "short": "Marital (civil) status of a patient", + "definition": "This field contains a patient's most recent marital (civil) status.", + "comment": "Not all terminology uses fit this general pattern. In some cases, models should not use CodeableConcept and use Coding directly and provide their own structure for managing text, codings, translations and the relationship between elements and pre- and post-coordination.", + "requirements": "Most, if not all systems capture it.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.maritalStatus", + "max": "1" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "MaritalStatus" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true } + ], + "strength": "extensible", + "description": "The domestic partnership status of a person.", + "valueSet": "http://hl7.org/fhir/ValueSet/marital-status" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "CE/CNE/CWE" + }, + { + "identity": "rim", + "map": "CD" + }, + { + "identity": "orim", + "map": "fhir:CodeableConcept rdfs:subClassOf dt:CD" + }, + { + "identity": "v2", + "map": "PID-16" + }, + { + "identity": "rim", + "map": "player[classCode=PSN]/maritalStatusCode" + }, + { + "identity": "cda", + "map": ".patient.maritalStatusCode" + } ] - }, - "differential": { - "element": [ - { - "id": "Patient", - "path": "Patient", - "short": "Information about an individual or animal receiving health care services", - "definition": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", - "alias": [ "SubjectOfCare Client Resident" ], - "min": 0, - "max": "*", - "mustSupport": false, - "isModifier": false, - "mapping": [ - { - "identity": "rim", - "map": "Patient[classCode=PAT]" - }, - { - "identity": "cda", - "map": "ClinicalDocument.recordTarget.patientRole" - }, - { - "identity": "w5", - "map": "administrative.individual" - } - ] - }, - { - "id": "Patient.identifier", - "path": "Patient.identifier", - "short": "An identifier for this patient", - "definition": "An identifier for this patient.", - "requirements": "Patients are almost always assigned specific numerical identifiers.", - "min": 0, - "max": "*", - "type": [ - { - "code": "Identifier" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "w5", - "map": "FiveWs.identifier" - }, - { - "identity": "v2", - "map": "PID-3" - }, - { - "identity": "rim", - "map": "id" - }, - { - "identity": "cda", - "map": ".id" - } - ] - }, - { - "id": "Patient.active", - "path": "Patient.active", - "short": "Whether this patient's record is in active use", - "definition": "Whether this patient record is in active use. \nMany systems use this property to mark as non-current patients, such as those that have not been seen for a period of time based on an organization's business rules.\n\nIt is often used to filter patient lists to exclude inactive patients\n\nDeceased patients may also be marked as inactive for the same reasons, but may be active for some time after death.", - "comment": "If a record is inactive, and linked to an active record, then future patient/record updates should occur on the other patient.", - "requirements": "Need to be able to mark a patient record as not to be used because it was created in error.", - "min": 0, - "max": "1", - "type": [ - { - "code": "boolean" - } - ], - "meaningWhenMissing": "This resource is generally assumed to be active if no value is provided for the active element", - "mustSupport": false, - "isModifier": true, - "isModifierReason": "This element is labelled as a modifier because it is a status element that can indicate that a record should not be treated as valid", - "isSummary": true, - "mapping": [ - { - "identity": "w5", - "map": "FiveWs.status" - }, - { - "identity": "rim", - "map": "statusCode" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.name", - "path": "Patient.name", - "short": "A name associated with the patient", - "definition": "A name associated with the individual.", - "comment": "A patient may have multiple names with different uses or applicable periods. For animals, the name is a \"HumanName\" in the sense that is assigned and used by humans and has the same patterns.", - "requirements": "Need to be able to track the patient by multiple names. Examples are your official name and a partner name.", - "min": 0, - "max": "*", - "type": [ - { - "code": "HumanName" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-5, PID-9" - }, - { - "identity": "rim", - "map": "name" - }, - { - "identity": "cda", - "map": ".patient.name" - } - ] - }, - { - "id": "Patient.telecom", - "path": "Patient.telecom", - "short": "A contact detail for the individual", - "definition": "A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted.", - "comment": "A Patient may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently and also to help with identification. The address might not go directly to the individual, but may reach another party that is able to proxy for the patient (i.e. home phone, or pet owner's phone).", - "requirements": "People have (primary) ways to contact them in some way such as phone, email.", - "min": 0, - "max": "*", - "type": [ - { - "code": "ContactPoint" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-13, PID-14, PID-40" - }, - { - "identity": "rim", - "map": "telecom" - }, - { - "identity": "cda", - "map": ".telecom" - } - ] - }, - { - "id": "Patient.gender", - "path": "Patient.gender", - "short": "male | female | other | unknown", - "definition": "Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes.", - "comment": "The gender might not match the biological sex as determined by genetics or the individual's preferred identification. Note that for both humans and particularly animals, there are other legitimate possibilities than male and female, though the vast majority of systems and contexts only support male and female. Systems providing decision support or enforcing business rules should ideally do this on the basis of Observations dealing with the specific sex or gender aspect of interest (anatomical, chromosomal, social, etc.) However, because these observations are infrequently recorded, defaulting to the administrative gender is common practice. Where such defaulting occurs, rule enforcement should allow for the variation between administrative and biological, chromosomal and other gender aspects. For example, an alert about a hysterectomy on a male should be handled as a warning or overridable error, not a \"hard\" error. See the Patient Gender and Sex section for additional information about communicating patient gender and sex.", - "requirements": "Needed for identification of the individual, in combination with (at least) name and birth date.", - "min": 0, - "max": "1", - "type": [ - { - "code": "code" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "AdministrativeGender" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", - "valueBoolean": true - } - ], - "strength": "required", - "description": "The gender of a person used for administrative purposes.", - "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" - }, - "mapping": [ - { - "identity": "v2", - "map": "PID-8" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" - }, - { - "identity": "cda", - "map": ".patient.administrativeGenderCode" - } - ] - }, - { - "id": "Patient.birthDate", - "path": "Patient.birthDate", - "short": "The date of birth for the individual", - "definition": "The date of birth for the individual.", - "comment": "At least an estimated year should be provided as a guess if the real DOB is unknown There is a standard extension \"patient-birthTime\" available that should be used where Time is required (such as in maternity/infant care systems).", - "requirements": "Age of the individual drives many clinical processes.", - "min": 0, - "max": "1", - "type": [ - { - "code": "date" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-7" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/birthTime" - }, - { - "identity": "cda", - "map": ".patient.birthTime" - }, - { - "identity": "loinc", - "map": "21112-8" - } - ] - }, - { - "id": "Patient.deceased[x]", - "path": "Patient.deceased[x]", - "short": "Indicates if the individual is deceased or not", - "definition": "Indicates if the individual is deceased or not.", - "comment": "If there's no value in the instance, it means there is no statement on whether or not the individual is deceased. Most systems will interpret the absence of a value as a sign of the person being alive.", - "requirements": "The fact that a patient is deceased influences the clinical process. Also, in human communication and relation management it is necessary to know whether the person is alive.", - "min": 0, - "max": "1", - "type": [ - { - "code": "boolean" - }, - { - "code": "dateTime" - } - ], - "mustSupport": false, - "isModifier": true, - "isModifierReason": "This element is labeled as a modifier because once a patient is marked as deceased, the actions that are appropriate to perform on the patient may be significantly different.", - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-30 (bool) and PID-29 (datetime)" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedTime" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.address", - "path": "Patient.address", - "short": "An address for the individual", - "definition": "An address for the individual.", - "comment": "Patient may have multiple addresses with different uses or applicable periods.", - "requirements": "May need to keep track of patient addresses for contacting, billing or reporting requirements and also to help with identification.", - "min": 0, - "max": "*", - "type": [ - { - "code": "Address" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-11" - }, - { - "identity": "rim", - "map": "addr" - }, - { - "identity": "cda", - "map": ".addr" - } - ] - }, - { - "id": "Patient.maritalStatus", - "path": "Patient.maritalStatus", - "short": "Marital (civil) status of a patient", - "definition": "This field contains a patient's most recent marital (civil) status.", - "requirements": "Most, if not all systems capture it.", - "min": 0, - "max": "1", - "type": [ - { - "code": "CodeableConcept" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "MaritalStatus" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", - "valueBoolean": true - } - ], - "strength": "extensible", - "description": "The domestic partnership status of a person.", - "valueSet": "http://hl7.org/fhir/ValueSet/marital-status" - }, - "mapping": [ - { - "identity": "v2", - "map": "PID-16" - }, - { - "identity": "rim", - "map": "player[classCode=PSN]/maritalStatusCode" - }, - { - "identity": "cda", - "map": ".patient.maritalStatusCode" - } - ] - }, - { - "id": "Patient.multipleBirth[x]", - "path": "Patient.multipleBirth[x]", - "short": "Whether patient is part of a multiple birth", - "definition": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", - "comment": "Where the valueInteger is provided, the number is the birth number in the sequence. E.g. The middle birth in triplets would be valueInteger=2 and the third born would have valueInteger=3 If a boolean value was provided for this triplets example, then all 3 patient records would have valueBoolean=true (the ordering is not indicated).", - "requirements": "For disambiguation of multiple-birth children, especially relevant where the care provider doesn't meet the patient, such as labs.", - "min": 0, - "max": "1", - "type": [ - { - "code": "boolean" - }, - { - "code": "integer" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "PID-24 (bool), PID-25 (integer)" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthOrderNumber" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.photo", - "path": "Patient.photo", - "short": "Image of the patient", - "definition": "Image of the patient.", - "comment": "Guidelines:\n* Use id photos, not clinical photos.\n* Limit dimensions to thumbnail.\n* Keep byte count low to ease resource updates.", - "requirements": "Many EHR systems have the capability to capture an image of the patient. Fits with newer social media usage too.", - "min": 0, - "max": "*", - "type": [ - { - "code": "Attachment" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "OBX-5 - needs a profile" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/desc" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact", - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name", - "valueString": "Contact" - } - ], - "path": "Patient.contact", - "short": "A contact party (e.g. guardian, partner, friend) for the patient", - "definition": "A contact party (e.g. guardian, partner, friend) for the patient.", - "comment": "Contact covers all kinds of contact parties: family members, business contacts, guardians, caregivers. Not applicable to register pedigree and family ties beyond use of having contact.", - "requirements": "Need to track people you can contact about the patient.", - "min": 0, - "max": "*", - "type": [ - { - "code": "BackboneElement" - } - ], - "constraint": [ - { - "key": "pat-1", - "severity": "error", - "human": "SHALL at least contain a contact's details or a reference to an organization", - "expression": "name.exists() or telecom.exists() or address.exists() or organization.exists()", - "xpath": "exists(f:name) or exists(f:telecom) or exists(f:address) or exists(f:organization)", - "source": "http://hl7.org/fhir/StructureDefinition/Patient" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/scopedRole[classCode=CON]" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.relationship", - "path": "Patient.contact.relationship", - "short": "The kind of relationship", - "definition": "The nature of the relationship between the patient and the contact person.", - "requirements": "Used to determine which contact person is the most relevant to approach, depending on circumstances.", - "min": 0, - "max": "*", - "type": [ - { - "code": "CodeableConcept" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "ContactRelationship" - } - ], - "strength": "extensible", - "description": "The nature of the relationship between a patient and a contact person for that patient.", - "valueSet": "http://hl7.org/fhir/ValueSet/patient-contactrelationship" - }, - "mapping": [ - { - "identity": "v2", - "map": "NK1-7, NK1-3" - }, - { - "identity": "rim", - "map": "code" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.name", - "path": "Patient.contact.name", - "short": "A name associated with the contact person", - "definition": "A name associated with the contact person.", - "requirements": "Contact persons need to be identified by name, but it is uncommon to need details about multiple other names for that contact person.", - "min": 0, - "max": "1", - "type": [ - { - "code": "HumanName" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "NK1-2" - }, - { - "identity": "rim", - "map": "name" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.telecom", - "path": "Patient.contact.telecom", - "short": "A contact detail for the person", - "definition": "A contact detail for the person, e.g. a telephone number or an email address.", - "comment": "Contact may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently, and also to help with identification.", - "requirements": "People have (primary) ways to contact them in some way such as phone, email.", - "min": 0, - "max": "*", - "type": [ - { - "code": "ContactPoint" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "NK1-5, NK1-6, NK1-40" - }, - { - "identity": "rim", - "map": "telecom" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.address", - "path": "Patient.contact.address", - "short": "Address for the contact person", - "definition": "Address for the contact person.", - "requirements": "Need to keep track where the contact person can be contacted per postal mail or visited.", - "min": 0, - "max": "1", - "type": [ - { - "code": "Address" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "NK1-4" - }, - { - "identity": "rim", - "map": "addr" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.gender", - "path": "Patient.contact.gender", - "short": "male | female | other | unknown", - "definition": "Administrative Gender - the gender that the contact person is considered to have for administration and record keeping purposes.", - "requirements": "Needed to address the person correctly.", - "min": 0, - "max": "1", - "type": [ - { - "code": "code" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "AdministrativeGender" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", - "valueBoolean": true - } - ], - "strength": "required", - "description": "The gender of a person used for administrative purposes.", - "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" - }, - "mapping": [ - { - "identity": "v2", - "map": "NK1-15" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.organization", - "path": "Patient.contact.organization", - "short": "Organization that is associated with the contact", - "definition": "Organization on behalf of which the contact is acting or for which the contact is working.", - "requirements": "For guardians or business related contacts, the organization is relevant.", - "min": 0, - "max": "1", - "type": [ - { - "code": "Reference", - "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] - } - ], - "condition": [ "pat-1" ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "NK1-13, NK1-30, NK1-31, NK1-32, NK1-41" - }, - { - "identity": "rim", - "map": "scoper" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.contact.period", - "path": "Patient.contact.period", - "short": "The period during which this contact person or organization is valid to be contacted relating to this patient", - "definition": "The period during which this contact person or organization is valid to be contacted relating to this patient.", - "min": 0, - "max": "1", - "type": [ - { - "code": "Period" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "effectiveTime" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.communication", - "path": "Patient.communication", - "short": "A language which may be used to communicate with the patient about his or her health", - "definition": "A language which may be used to communicate with the patient about his or her health.", - "comment": "If no language is specified, this *implies* that the default local language is spoken. If you need to convey proficiency for multiple modes, then you need multiple Patient.Communication associations. For animals, language is not a relevant field, and should be absent from the instance. If the Patient does not speak the default local language, then the Interpreter Required Standard can be used to explicitly declare that an interpreter is required.", - "requirements": "If a patient does not speak the local language, interpreters may be required, so languages spoken and proficiency are important things to keep track of both for patient and other persons of interest.", - "min": 0, - "max": "*", - "type": [ - { - "code": "BackboneElement" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "rim", - "map": "LanguageCommunication" - }, - { - "identity": "cda", - "map": "patient.languageCommunication" - } - ] - }, - { - "id": "Patient.communication.language", - "path": "Patient.communication.language", - "short": "The language which can be used to communicate with the patient about his or her health", - "definition": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-EN\" for England English.", - "comment": "The structure aa-BB with this exact casing is one the most widely used notations for locale. However not all systems actually code this but instead have it as free text. Hence CodeableConcept instead of code as the data type.", - "requirements": "Most systems in multilingual countries will want to convey language. Not all systems actually need the regional dialect.", - "min": 1, - "max": "1", - "type": [ - { - "code": "CodeableConcept" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", - "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "Language" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", - "valueBoolean": true - } - ], - "strength": "preferred", - "description": "IETF language tag", - "valueSet": "http://hl7.org/fhir/ValueSet/languages" - }, - "mapping": [ - { - "identity": "v2", - "map": "PID-15, LAN-2" - }, - { - "identity": "rim", - "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/languageCommunication/code" - }, - { - "identity": "cda", - "map": ".languageCode" - } - ] - }, - { - "id": "Patient.communication.preferred", - "path": "Patient.communication.preferred", - "short": "Language preference indicator", - "definition": "Indicates whether or not the patient prefers this language (over other languages he masters up a certain level).", - "comment": "This language is specifically identified for communicating healthcare information.", - "requirements": "People that master multiple languages up to certain level may prefer one or more, i.e. feel more confident in communicating in a particular language making other languages sort of a fall back method.", - "min": 0, - "max": "1", - "type": [ - { - "code": "boolean" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "PID-15" - }, - { - "identity": "rim", - "map": "preferenceInd" - }, - { - "identity": "cda", - "map": ".preferenceInd" - } - ] - }, - { - "id": "Patient.generalPractitioner", - "path": "Patient.generalPractitioner", - "short": "Patient's nominated primary care provider", - "definition": "Patient's nominated care provider.", - "comment": "This may be the primary care provider (in a GP context), or it may be a patient nominated care manager in a community/disability setting, or even organization that will provide people to perform the care provider roles. It is not to be used to record Care Teams, these should be in a CareTeam resource that may be linked to the CarePlan or EpisodeOfCare resources.\nMultiple GPs may be recorded against the patient for various reasons, such as a student that has his home GP listed along with the GP at university during the school semesters, or a \"fly-in/fly-out\" worker that has the onsite GP also included with his home GP to remain aware of medical issues.\n\nJurisdictions may decide that they can profile this down to 1 if desired, or 1 per type.", - "alias": [ "careProvider" ], - "min": 0, - "max": "*", - "type": [ - { - "code": "Reference", - "targetProfile": [ - "http://hl7.org/fhir/StructureDefinition/Organization", - "http://hl7.org/fhir/StructureDefinition/Practitioner", - "http://hl7.org/fhir/StructureDefinition/PractitionerRole" - ] - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": false, - "mapping": [ - { - "identity": "v2", - "map": "PD1-4" - }, - { - "identity": "rim", - "map": "subjectOf.CareEvent.performer.AssignedEntity" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.managingOrganization", - "path": "Patient.managingOrganization", - "short": "Organization that is the custodian of the patient record", - "definition": "Organization that is the custodian of the patient record.", - "comment": "There is only one managing organization for a specific patient record. Other organizations will have their own Patient record, and may use the Link property to join the records together (or a Person resource which can include confidence ratings for the association).", - "requirements": "Need to know who recognizes this patient record, manages and updates it.", - "min": 0, - "max": "1", - "type": [ - { - "code": "Reference", - "targetProfile": [ "http://hl7.org/fhir/StructureDefinition/Organization" ] - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "rim", - "map": "scoper" - }, - { - "identity": "cda", - "map": ".providerOrganization" - } - ] - }, - { - "id": "Patient.link", - "path": "Patient.link", - "short": "Link to another patient resource that concerns the same actual person", - "definition": "Link to another patient resource that concerns the same actual patient.", - "comment": "There is no assumption that linked patient records have mutual links.", - "requirements": "There are multiple use cases: \n\n* Duplicate patient records due to the clerical errors associated with the difficulties of identifying humans consistently, and \n* Distribution of patient information across multiple servers.", - "min": 0, - "max": "*", - "type": [ - { - "code": "BackboneElement" - } - ], - "mustSupport": false, - "isModifier": true, - "isModifierReason": "This element is labeled as a modifier because it might not be the main Patient resource, and the referenced patient should be used instead of this Patient record. This is when the link.type value is 'replaced-by'", - "isSummary": true, - "mapping": [ - { - "identity": "rim", - "map": "outboundLink" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.link.other", - "path": "Patient.link.other", - "short": "The other patient or related person resource that the link refers to", - "definition": "The other patient resource that the link refers to.", - "comment": "Referencing a RelatedPerson here removes the need to use a Person record to associate a Patient and RelatedPerson as the same individual.", - "min": 1, - "max": "1", - "type": [ - { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy", - "valueBoolean": false - } - ], - "code": "Reference", - "targetProfile": [ - "http://hl7.org/fhir/StructureDefinition/Patient", - "http://hl7.org/fhir/StructureDefinition/RelatedPerson" - ] - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "mapping": [ - { - "identity": "v2", - "map": "PID-3, MRG-1" - }, - { - "identity": "rim", - "map": "id" - }, - { - "identity": "cda", - "map": "n/a" - } - ] - }, - { - "id": "Patient.link.type", - "path": "Patient.link.type", - "short": "replaced-by | replaces | refer | seealso", - "definition": "The type of link between this patient resource and another patient resource.", - "min": 1, - "max": "1", - "type": [ - { - "code": "code" - } - ], - "mustSupport": false, - "isModifier": false, - "isSummary": true, - "binding": { - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", - "valueString": "LinkType" - } - ], - "strength": "required", - "description": "The type of link between this patient resource and another patient resource.", - "valueSet": "http://hl7.org/fhir/ValueSet/link-type|4.3.0" - }, - "mapping": [ - { - "identity": "rim", - "map": "typeCode" - }, - { - "identity": "cda", - "map": "n/a" - } - ] + }, + { + "id": "Patient.multipleBirth[x]", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.multipleBirth[x]", + "short": "Whether patient is part of a multiple birth", + "definition": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", + "comment": "Where the valueInteger is provided, the number is the birth number in the sequence. E.g. The middle birth in triplets would be valueInteger=2 and the third born would have valueInteger=3 If a boolean value was provided for this triplets example, then all 3 patient records would have valueBoolean=true (the ordering is not indicated).", + "requirements": "For disambiguation of multiple-birth children, especially relevant where the care provider doesn't meet the patient, such as labs.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.multipleBirth[x]", + "max": "1" + }, + "type": [ + { + "code": "boolean" + }, + { + "code": "integer" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "PID-24 (bool), PID-25 (integer)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthOrderNumber" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.photo", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.photo", + "short": "Image of the patient", + "definition": "Image of the patient.", + "comment": "Guidelines:\n* Use id photos, not clinical photos.\n* Limit dimensions to thumbnail.\n* Keep byte count low to ease resource updates.", + "requirements": "Many EHR systems have the capability to capture an image of the patient. Fits with newer social media usage too.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.photo" + }, + "type": [ + { + "code": "Attachment" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "att-1", + "severity": "error", + "human": "If the Attachment has data, it SHALL have a contentType", + "expression": "data.empty() or contentType.exists()", + "xpath": "not(exists(f:data)) or exists(f:contentType)", + "source": "http://hl7.org/fhir/StructureDefinition/Attachment" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "ED/RP" + }, + { + "identity": "rim", + "map": "ED" + }, + { + "identity": "v2", + "map": "OBX-5 - needs a profile" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/desc" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name", + "valueString": "Contact" + } + ], + "path": "Patient.contact", + "short": "A contact party (e.g. guardian, partner, friend) for the patient", + "definition": "A contact party (e.g. guardian, partner, friend) for the patient.", + "comment": "Contact covers all kinds of contact parties: family members, business contacts, guardians, caregivers. Not applicable to register pedigree and family ties beyond use of having contact.", + "requirements": "Need to track people you can contact about the patient.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.contact" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "pat-1", + "severity": "error", + "human": "SHALL at least contain a contact's details or a reference to an organization", + "expression": "name.exists() or telecom.exists() or address.exists() or organization.exists()", + "xpath": "exists(f:name) or exists(f:telecom) or exists(f:address) or exists(f:organization)", + "source": "http://hl7.org/fhir/StructureDefinition/Patient" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/scopedRole[classCode=CON]" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.id", + "path": "Patient.contact.id", + "representation": [ + "xmlAttr" + ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "id" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.extension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.contact.extension", + "slicing": { + "discriminator": [ + { + "type": "value", + "path": "url" } + ], + "description": "Extensions are always sliced by (at least) url", + "rules": "open" + }, + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } ] - } -} + }, + { + "id": "Patient.contact.modifierExtension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.contact.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.contact.relationship", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.contact.relationship", + "short": "The kind of relationship", + "definition": "The nature of the relationship between the patient and the contact person.", + "comment": "Not all terminology uses fit this general pattern. In some cases, models should not use CodeableConcept and use Coding directly and provide their own structure for managing text, codings, translations and the relationship between elements and pre- and post-coordination.", + "requirements": "Used to determine which contact person is the most relevant to approach, depending on circumstances.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.contact.relationship" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "ContactRelationship" + } + ], + "strength": "extensible", + "description": "The nature of the relationship between a patient and a contact person for that patient.", + "valueSet": "http://hl7.org/fhir/ValueSet/patient-contactrelationship" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "CE/CNE/CWE" + }, + { + "identity": "rim", + "map": "CD" + }, + { + "identity": "orim", + "map": "fhir:CodeableConcept rdfs:subClassOf dt:CD" + }, + { + "identity": "v2", + "map": "NK1-7, NK1-3" + }, + { + "identity": "rim", + "map": "code" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.name", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.contact.name", + "short": "A name associated with the contact person", + "definition": "A name associated with the contact person.", + "comment": "Names may be changed, or repudiated, or people may have different names in different contexts. Names may be divided into parts of different type that have variable significance depending on context, though the division into parts does not always matter. With personal names, the different parts might or might not be imbued with some implicit meaning; various cultures associate different importance with the name parts and the degree to which systems must care about name parts around the world varies widely.", + "requirements": "Contact persons need to be identified by name, but it is uncommon to need details about multiple other names for that contact person.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.name", + "max": "1" + }, + "type": [ + { + "code": "HumanName" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "XPN" + }, + { + "identity": "rim", + "map": "EN (actually, PN)" + }, + { + "identity": "servd", + "map": "ProviderName" + }, + { + "identity": "v2", + "map": "NK1-2" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.telecom", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.contact.telecom", + "short": "A contact detail for the person", + "definition": "A contact detail for the person, e.g. a telephone number or an email address.", + "comment": "Contact may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently, and also to help with identification.", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.contact.telecom" + }, + "type": [ + { + "code": "ContactPoint" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "cpt-2", + "severity": "error", + "human": "A system is required if a value is provided.", + "expression": "value.empty() or system.exists()", + "xpath": "not(exists(f:value)) or exists(f:system)", + "source": "http://hl7.org/fhir/StructureDefinition/ContactPoint" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "XTN" + }, + { + "identity": "rim", + "map": "TEL" + }, + { + "identity": "servd", + "map": "ContactPoint" + }, + { + "identity": "v2", + "map": "NK1-5, NK1-6, NK1-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.address", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.contact.address", + "short": "Address for the contact person", + "definition": "Address for the contact person.", + "comment": "Note: address is intended to describe postal addresses for administrative purposes, not to describe absolute geographical coordinates. Postal addresses are often used as proxies for physical locations (also see the [Location](location.html#) resource).", + "requirements": "Need to keep track where the contact person can be contacted per postal mail or visited.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.address", + "max": "1" + }, + "type": [ + { + "code": "Address" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "XAD" + }, + { + "identity": "rim", + "map": "AD" + }, + { + "identity": "servd", + "map": "Address" + }, + { + "identity": "v2", + "map": "NK1-4" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.gender", + "path": "Patient.contact.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the contact person is considered to have for administration and record keeping purposes.", + "comment": "Note that FHIR strings SHALL NOT exceed 1MB in size", + "requirements": "Needed to address the person correctly.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.gender", + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "NK1-15" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.organization", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.contact.organization", + "short": "Organization that is associated with the contact", + "definition": "Organization on behalf of which the contact is acting or for which the contact is working.", + "comment": "References SHALL be a reference to an actual FHIR resource, and SHALL be resolveable (allowing for access control, temporary unavailability, etc.). Resolution can be either by retrieval from the URL, or, where applicable by resource type, by treating an absolute reference as a canonical URL and looking it up in a local registry/repository.", + "requirements": "For guardians or business related contacts, the organization is relevant.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.organization", + "max": "1" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization" + ] + } + ], + "condition": [ + "ele-1", + "pat-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ref-1", + "severity": "error", + "human": "SHALL have a contained resource if a local reference is provided", + "expression": "reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids')) or (reference='#' and %rootResource!=%resource)", + "xpath": "not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])", + "source": "http://hl7.org/fhir/StructureDefinition/Reference" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "The target of a resource reference is a RIM entry point (Act, Role, or Entity)" + }, + { + "identity": "v2", + "map": "NK1-13, NK1-30, NK1-31, NK1-32, NK1-41" + }, + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.period", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.contact.period", + "short": "The period during which this contact person or organization is valid to be contacted relating to this patient", + "definition": "The period during which this contact person or organization is valid to be contacted relating to this patient.", + "comment": "A Period specifies a range of time; the context of use will specify whether the entire range applies (e.g. \"the patient was an inpatient of the hospital for this time range\") or one value from the range applies (e.g. \"give to the patient between these two times\").\n\nPeriod is not used for a duration (a measure of elapsed time). See [Duration](datatypes.html#Duration).", + "min": 0, + "max": "1", + "base": { + "path": "Patient.contact.period", + "max": "1" + }, + "type": [ + { + "code": "Period" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "per-1", + "severity": "error", + "human": "If present, start SHALL have a lower value than end", + "expression": "start.hasValue().not() or end.hasValue().not() or (start <= end)", + "xpath": "not(exists(f:start/@value)) or not(exists(f:end/@value)) or (xs:dateTime(f:start/@value) <= xs:dateTime(f:end/@value))", + "source": "http://hl7.org/fhir/StructureDefinition/Period" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "DR" + }, + { + "identity": "rim", + "map": "IVL[lowClosed=\"true\" and highClosed=\"true\"] or URG[lowClosed=\"true\" and highClosed=\"true\"]" + }, + { + "identity": "rim", + "map": "effectiveTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.communication", + "short": "A language which may be used to communicate with the patient about his or her health", + "definition": "A language which may be used to communicate with the patient about his or her health.", + "comment": "If no language is specified, this *implies* that the default local language is spoken. If you need to convey proficiency for multiple modes, then you need multiple Patient.Communication associations. For animals, language is not a relevant field, and should be absent from the instance. If the Patient does not speak the default local language, then the Interpreter Required Standard can be used to explicitly declare that an interpreter is required.", + "requirements": "If a patient does not speak the local language, interpreters may be required, so languages spoken and proficiency are important things to keep track of both for patient and other persons of interest.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.communication" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "LanguageCommunication" + }, + { + "identity": "cda", + "map": "patient.languageCommunication" + } + ] + }, + { + "id": "Patient.communication.id", + "path": "Patient.communication.id", + "representation": [ + "xmlAttr" + ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "id" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication.extension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.communication.extension", + "slicing": { + "discriminator": [ + { + "type": "value", + "path": "url" + } + ], + "description": "Extensions are always sliced by (at least) url", + "rules": "open" + }, + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.communication.modifierExtension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.communication.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.communication.language", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.communication.language", + "short": "The language which can be used to communicate with the patient about his or her health", + "definition": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-EN\" for England English.", + "comment": "The structure aa-BB with this exact casing is one the most widely used notations for locale. However not all systems actually code this but instead have it as free text. Hence CodeableConcept instead of code as the data type.", + "requirements": "Most systems in multilingual countries will want to convey language. Not all systems actually need the regional dialect.", + "min": 1, + "max": "1", + "base": { + "path": "Patient.communication.language", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "CE/CNE/CWE" + }, + { + "identity": "rim", + "map": "CD" + }, + { + "identity": "orim", + "map": "fhir:CodeableConcept rdfs:subClassOf dt:CD" + }, + { + "identity": "v2", + "map": "PID-15, LAN-2" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/languageCommunication/code" + }, + { + "identity": "cda", + "map": ".languageCode" + } + ] + }, + { + "id": "Patient.communication.preferred", + "path": "Patient.communication.preferred", + "short": "Language preference indicator", + "definition": "Indicates whether or not the patient prefers this language (over other languages he masters up a certain level).", + "comment": "This language is specifically identified for communicating healthcare information.", + "requirements": "People that master multiple languages up to certain level may prefer one or more, i.e. feel more confident in communicating in a particular language making other languages sort of a fall back method.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.communication.preferred", + "max": "1" + }, + "type": [ + { + "code": "boolean" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "v2", + "map": "PID-15" + }, + { + "identity": "rim", + "map": "preferenceInd" + }, + { + "identity": "cda", + "map": ".preferenceInd" + } + ] + }, + { + "id": "Patient.generalPractitioner", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.generalPractitioner", + "short": "Patient's nominated primary care provider", + "definition": "Patient's nominated care provider.", + "comment": "This may be the primary care provider (in a GP context), or it may be a patient nominated care manager in a community/disability setting, or even organization that will provide people to perform the care provider roles. It is not to be used to record Care Teams, these should be in a CareTeam resource that may be linked to the CarePlan or EpisodeOfCare resources.\nMultiple GPs may be recorded against the patient for various reasons, such as a student that has his home GP listed along with the GP at university during the school semesters, or a \"fly-in/fly-out\" worker that has the onsite GP also included with his home GP to remain aware of medical issues.\n\nJurisdictions may decide that they can profile this down to 1 if desired, or 1 per type.", + "alias": [ + "careProvider" + ], + "min": 0, + "max": "*", + "base": { + "path": "Patient.generalPractitioner" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization", + "http://hl7.org/fhir/StructureDefinition/Practitioner", + "http://hl7.org/fhir/StructureDefinition/PractitionerRole" + ] + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ref-1", + "severity": "error", + "human": "SHALL have a contained resource if a local reference is provided", + "expression": "reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids')) or (reference='#' and %rootResource!=%resource)", + "xpath": "not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])", + "source": "http://hl7.org/fhir/StructureDefinition/Reference" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "The target of a resource reference is a RIM entry point (Act, Role, or Entity)" + }, + { + "identity": "v2", + "map": "PD1-4" + }, + { + "identity": "rim", + "map": "subjectOf.CareEvent.performer.AssignedEntity" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.managingOrganization", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.managingOrganization", + "short": "Organization that is the custodian of the patient record", + "definition": "Organization that is the custodian of the patient record.", + "comment": "There is only one managing organization for a specific patient record. Other organizations will have their own Patient record, and may use the Link property to join the records together (or a Person resource which can include confidence ratings for the association).", + "requirements": "Need to know who recognizes this patient record, manages and updates it.", + "min": 0, + "max": "1", + "base": { + "path": "Patient.managingOrganization", + "max": "1" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization" + ] + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ref-1", + "severity": "error", + "human": "SHALL have a contained resource if a local reference is provided", + "expression": "reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids')) or (reference='#' and %rootResource!=%resource)", + "xpath": "not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])", + "source": "http://hl7.org/fhir/StructureDefinition/Reference" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "The target of a resource reference is a RIM entry point (Act, Role, or Entity)" + }, + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": ".providerOrganization" + } + ] + }, + { + "id": "Patient.link", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.link", + "short": "Link to another patient resource that concerns the same actual person", + "definition": "Link to another patient resource that concerns the same actual patient.", + "comment": "There is no assumption that linked patient records have mutual links.", + "requirements": "There are multiple use cases: \n\n* Duplicate patient records due to the clerical errors associated with the difficulties of identifying humans consistently, and \n* Distribution of patient information across multiple servers.", + "min": 0, + "max": "*", + "base": { + "path": "Patient.link" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because it might not be the main Patient resource, and the referenced patient should be used instead of this Patient record. This is when the link.type value is 'replaced-by'", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "outboundLink" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.id", + "path": "Patient.link.id", + "representation": [ + "xmlAttr" + ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "id" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.extension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.link.extension", + "slicing": { + "discriminator": [ + { + "type": "value", + "path": "url" + } + ], + "description": "Extensions are always sliced by (at least) url", + "rules": "open" + }, + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.link.modifierExtension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.link.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Patient.link.other", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Patient.link.other", + "short": "The other patient or related person resource that the link refers to", + "definition": "The other patient resource that the link refers to.", + "comment": "Referencing a RelatedPerson here removes the need to use a Person record to associate a Patient and RelatedPerson as the same individual.", + "min": 1, + "max": "1", + "base": { + "path": "Patient.link.other", + "min": 1, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy", + "valueBoolean": false + } + ], + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Patient", + "http://hl7.org/fhir/StructureDefinition/RelatedPerson" + ] + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ref-1", + "severity": "error", + "human": "SHALL have a contained resource if a local reference is provided", + "expression": "reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids')) or (reference='#' and %rootResource!=%resource)", + "xpath": "not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])", + "source": "http://hl7.org/fhir/StructureDefinition/Reference" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "The target of a resource reference is a RIM entry point (Act, Role, or Entity)" + }, + { + "identity": "v2", + "map": "PID-3, MRG-1" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.type", + "path": "Patient.link.type", + "short": "replaced-by | replaces | refer | seealso", + "definition": "The type of link between this patient resource and another patient resource.", + "comment": "Note that FHIR strings SHALL NOT exceed 1MB in size", + "min": 1, + "max": "1", + "base": { + "path": "Patient.link.type", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "LinkType" + } + ], + "strength": "required", + "description": "The type of link between this patient resource and another patient resource.", + "valueSet": "http://hl7.org/fhir/ValueSet/link-type|4.3.0" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "typeCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + } + ] + }, + "differential": { + "element": [ + { + "id": "Patient", + "path": "Patient", + "short": "Information about an individual or animal receiving health care services", + "definition": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.", + "alias": [ + "SubjectOfCare Client Resident" + ], + "mapping": [ + { + "identity": "rim", + "map": "Patient[classCode=PAT]" + }, + { + "identity": "cda", + "map": "ClinicalDocument.recordTarget.patientRole" + }, + { + "identity": "w5", + "map": "administrative.individual" + } + ] + }, + { + "id": "Patient.identifier", + "path": "Patient.identifier", + "short": "An identifier for this patient", + "definition": "An identifier for this patient.", + "requirements": "Patients are almost always assigned specific numerical identifiers.", + "type": [ + { + "code": "Identifier" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.identifier" + }, + { + "identity": "v2", + "map": "PID-3" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": ".id" + } + ] + }, + { + "id": "Patient.active", + "path": "Patient.active", + "short": "Whether this patient's record is in active use", + "definition": "Whether this patient record is in active use. \nMany systems use this property to mark as non-current patients, such as those that have not been seen for a period of time based on an organization's business rules.\n\nIt is often used to filter patient lists to exclude inactive patients\n\nDeceased patients may also be marked as inactive for the same reasons, but may be active for some time after death.", + "comment": "If a record is inactive, and linked to an active record, then future patient/record updates should occur on the other patient.", + "requirements": "Need to be able to mark a patient record as not to be used because it was created in error.", + "max": "1", + "type": [ + { + "code": "boolean" + } + ], + "meaningWhenMissing": "This resource is generally assumed to be active if no value is provided for the active element", + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labelled as a modifier because it is a status element that can indicate that a record should not be treated as valid", + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.status" + }, + { + "identity": "rim", + "map": "statusCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.name", + "path": "Patient.name", + "short": "A name associated with the patient", + "definition": "A name associated with the individual.", + "comment": "A patient may have multiple names with different uses or applicable periods. For animals, the name is a \"HumanName\" in the sense that is assigned and used by humans and has the same patterns.", + "requirements": "Need to be able to track the patient by multiple names. Examples are your official name and a partner name.", + "type": [ + { + "code": "HumanName" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-5, PID-9" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": ".patient.name" + } + ] + }, + { + "id": "Patient.telecom", + "path": "Patient.telecom", + "short": "A contact detail for the individual", + "definition": "A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted.", + "comment": "A Patient may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently and also to help with identification. The address might not go directly to the individual, but may reach another party that is able to proxy for the patient (i.e. home phone, or pet owner's phone).", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "type": [ + { + "code": "ContactPoint" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-13, PID-14, PID-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": ".telecom" + } + ] + }, + { + "id": "Patient.gender", + "path": "Patient.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes.", + "comment": "The gender might not match the biological sex as determined by genetics or the individual's preferred identification. Note that for both humans and particularly animals, there are other legitimate possibilities than male and female, though the vast majority of systems and contexts only support male and female. Systems providing decision support or enforcing business rules should ideally do this on the basis of Observations dealing with the specific sex or gender aspect of interest (anatomical, chromosomal, social, etc.) However, because these observations are infrequently recorded, defaulting to the administrative gender is common practice. Where such defaulting occurs, rule enforcement should allow for the variation between administrative and biological, chromosomal and other gender aspects. For example, an alert about a hysterectomy on a male should be handled as a warning or overridable error, not a \"hard\" error. See the Patient Gender and Sex section for additional information about communicating patient gender and sex.", + "requirements": "Needed for identification of the individual, in combination with (at least) name and birth date.", + "max": "1", + "type": [ + { + "code": "code" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-8" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": ".patient.administrativeGenderCode" + } + ] + }, + { + "id": "Patient.birthDate", + "path": "Patient.birthDate", + "short": "The date of birth for the individual", + "definition": "The date of birth for the individual.", + "comment": "At least an estimated year should be provided as a guess if the real DOB is unknown There is a standard extension \"patient-birthTime\" available that should be used where Time is required (such as in maternity/infant care systems).", + "requirements": "Age of the individual drives many clinical processes.", + "max": "1", + "type": [ + { + "code": "date" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-7" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/birthTime" + }, + { + "identity": "cda", + "map": ".patient.birthTime" + }, + { + "identity": "loinc", + "map": "21112-8" + } + ] + }, + { + "id": "Patient.deceased[x]", + "path": "Patient.deceased[x]", + "short": "Indicates if the individual is deceased or not", + "definition": "Indicates if the individual is deceased or not.", + "comment": "If there's no value in the instance, it means there is no statement on whether or not the individual is deceased. Most systems will interpret the absence of a value as a sign of the person being alive.", + "requirements": "The fact that a patient is deceased influences the clinical process. Also, in human communication and relation management it is necessary to know whether the person is alive.", + "max": "1", + "type": [ + { + "code": "boolean" + }, + { + "code": "dateTime" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because once a patient is marked as deceased, the actions that are appropriate to perform on the patient may be significantly different.", + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-30 (bool) and PID-29 (datetime)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/deceasedTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.address", + "path": "Patient.address", + "short": "An address for the individual", + "definition": "An address for the individual.", + "comment": "Patient may have multiple addresses with different uses or applicable periods.", + "requirements": "May need to keep track of patient addresses for contacting, billing or reporting requirements and also to help with identification.", + "type": [ + { + "code": "Address" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-11" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": ".addr" + } + ] + }, + { + "id": "Patient.maritalStatus", + "path": "Patient.maritalStatus", + "short": "Marital (civil) status of a patient", + "definition": "This field contains a patient's most recent marital (civil) status.", + "requirements": "Most, if not all systems capture it.", + "max": "1", + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "MaritalStatus" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "extensible", + "description": "The domestic partnership status of a person.", + "valueSet": "http://hl7.org/fhir/ValueSet/marital-status" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-16" + }, + { + "identity": "rim", + "map": "player[classCode=PSN]/maritalStatusCode" + }, + { + "identity": "cda", + "map": ".patient.maritalStatusCode" + } + ] + }, + { + "id": "Patient.multipleBirth[x]", + "path": "Patient.multipleBirth[x]", + "short": "Whether patient is part of a multiple birth", + "definition": "Indicates whether the patient is part of a multiple (boolean) or indicates the actual birth order (integer).", + "comment": "Where the valueInteger is provided, the number is the birth number in the sequence. E.g. The middle birth in triplets would be valueInteger=2 and the third born would have valueInteger=3 If a boolean value was provided for this triplets example, then all 3 patient records would have valueBoolean=true (the ordering is not indicated).", + "requirements": "For disambiguation of multiple-birth children, especially relevant where the care provider doesn't meet the patient, such as labs.", + "max": "1", + "type": [ + { + "code": "boolean" + }, + { + "code": "integer" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-24 (bool), PID-25 (integer)" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthInd, player[classCode=PSN|ANM and determinerCode=INSTANCE]/multipleBirthOrderNumber" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.photo", + "path": "Patient.photo", + "short": "Image of the patient", + "definition": "Image of the patient.", + "comment": "Guidelines:\n* Use id photos, not clinical photos.\n* Limit dimensions to thumbnail.\n* Keep byte count low to ease resource updates.", + "requirements": "Many EHR systems have the capability to capture an image of the patient. Fits with newer social media usage too.", + "type": [ + { + "code": "Attachment" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "OBX-5 - needs a profile" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/desc" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name", + "valueString": "Contact" + } + ], + "path": "Patient.contact", + "short": "A contact party (e.g. guardian, partner, friend) for the patient", + "definition": "A contact party (e.g. guardian, partner, friend) for the patient.", + "comment": "Contact covers all kinds of contact parties: family members, business contacts, guardians, caregivers. Not applicable to register pedigree and family ties beyond use of having contact.", + "requirements": "Need to track people you can contact about the patient.", + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "pat-1", + "severity": "error", + "human": "SHALL at least contain a contact's details or a reference to an organization", + "expression": "name.exists() or telecom.exists() or address.exists() or organization.exists()", + "xpath": "exists(f:name) or exists(f:telecom) or exists(f:address) or exists(f:organization)" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/scopedRole[classCode=CON]" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.relationship", + "path": "Patient.contact.relationship", + "short": "The kind of relationship", + "definition": "The nature of the relationship between the patient and the contact person.", + "requirements": "Used to determine which contact person is the most relevant to approach, depending on circumstances.", + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "ContactRelationship" + } + ], + "strength": "extensible", + "description": "The nature of the relationship between a patient and a contact person for that patient.", + "valueSet": "http://hl7.org/fhir/ValueSet/patient-contactrelationship" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-7, NK1-3" + }, + { + "identity": "rim", + "map": "code" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.name", + "path": "Patient.contact.name", + "short": "A name associated with the contact person", + "definition": "A name associated with the contact person.", + "requirements": "Contact persons need to be identified by name, but it is uncommon to need details about multiple other names for that contact person.", + "max": "1", + "type": [ + { + "code": "HumanName" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-2" + }, + { + "identity": "rim", + "map": "name" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.telecom", + "path": "Patient.contact.telecom", + "short": "A contact detail for the person", + "definition": "A contact detail for the person, e.g. a telephone number or an email address.", + "comment": "Contact may have multiple ways to be contacted with different uses or applicable periods. May need to have options for contacting the person urgently, and also to help with identification.", + "requirements": "People have (primary) ways to contact them in some way such as phone, email.", + "type": [ + { + "code": "ContactPoint" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-5, NK1-6, NK1-40" + }, + { + "identity": "rim", + "map": "telecom" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.address", + "path": "Patient.contact.address", + "short": "Address for the contact person", + "definition": "Address for the contact person.", + "requirements": "Need to keep track where the contact person can be contacted per postal mail or visited.", + "max": "1", + "type": [ + { + "code": "Address" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-4" + }, + { + "identity": "rim", + "map": "addr" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.gender", + "path": "Patient.contact.gender", + "short": "male | female | other | unknown", + "definition": "Administrative Gender - the gender that the contact person is considered to have for administration and record keeping purposes.", + "requirements": "Needed to address the person correctly.", + "max": "1", + "type": [ + { + "code": "code" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "AdministrativeGender" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The gender of a person used for administrative purposes.", + "valueSet": "http://hl7.org/fhir/ValueSet/administrative-gender|4.3.0" + }, + "mapping": [ + { + "identity": "v2", + "map": "NK1-15" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/administrativeGender" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.organization", + "path": "Patient.contact.organization", + "short": "Organization that is associated with the contact", + "definition": "Organization on behalf of which the contact is acting or for which the contact is working.", + "requirements": "For guardians or business related contacts, the organization is relevant.", + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization" + ] + } + ], + "condition": [ + "pat-1" + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "NK1-13, NK1-30, NK1-31, NK1-32, NK1-41" + }, + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.contact.period", + "path": "Patient.contact.period", + "short": "The period during which this contact person or organization is valid to be contacted relating to this patient", + "definition": "The period during which this contact person or organization is valid to be contacted relating to this patient.", + "max": "1", + "type": [ + { + "code": "Period" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "effectiveTime" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.communication", + "path": "Patient.communication", + "short": "A language which may be used to communicate with the patient about his or her health", + "definition": "A language which may be used to communicate with the patient about his or her health.", + "comment": "If no language is specified, this *implies* that the default local language is spoken. If you need to convey proficiency for multiple modes, then you need multiple Patient.Communication associations. For animals, language is not a relevant field, and should be absent from the instance. If the Patient does not speak the default local language, then the Interpreter Required Standard can be used to explicitly declare that an interpreter is required.", + "requirements": "If a patient does not speak the local language, interpreters may be required, so languages spoken and proficiency are important things to keep track of both for patient and other persons of interest.", + "type": [ + { + "code": "BackboneElement" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "LanguageCommunication" + }, + { + "identity": "cda", + "map": "patient.languageCommunication" + } + ] + }, + { + "id": "Patient.communication.language", + "path": "Patient.communication.language", + "short": "The language which can be used to communicate with the patient about his or her health", + "definition": "The ISO-639-1 alpha 2 code in lower case for the language, optionally followed by a hyphen and the ISO-3166-1 alpha 2 code for the region in upper case; e.g. \"en\" for English, or \"en-US\" for American English versus \"en-EN\" for England English.", + "comment": "The structure aa-BB with this exact casing is one the most widely used notations for locale. However not all systems actually code this but instead have it as free text. Hence CodeableConcept instead of code as the data type.", + "requirements": "Most systems in multilingual countries will want to convey language. Not all systems actually need the regional dialect.", + "min": 1, + "max": "1", + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + }, + "mapping": [ + { + "identity": "v2", + "map": "PID-15, LAN-2" + }, + { + "identity": "rim", + "map": "player[classCode=PSN|ANM and determinerCode=INSTANCE]/languageCommunication/code" + }, + { + "identity": "cda", + "map": ".languageCode" + } + ] + }, + { + "id": "Patient.communication.preferred", + "path": "Patient.communication.preferred", + "short": "Language preference indicator", + "definition": "Indicates whether or not the patient prefers this language (over other languages he masters up a certain level).", + "comment": "This language is specifically identified for communicating healthcare information.", + "requirements": "People that master multiple languages up to certain level may prefer one or more, i.e. feel more confident in communicating in a particular language making other languages sort of a fall back method.", + "max": "1", + "type": [ + { + "code": "boolean" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PID-15" + }, + { + "identity": "rim", + "map": "preferenceInd" + }, + { + "identity": "cda", + "map": ".preferenceInd" + } + ] + }, + { + "id": "Patient.generalPractitioner", + "path": "Patient.generalPractitioner", + "short": "Patient's nominated primary care provider", + "definition": "Patient's nominated care provider.", + "comment": "This may be the primary care provider (in a GP context), or it may be a patient nominated care manager in a community/disability setting, or even organization that will provide people to perform the care provider roles. It is not to be used to record Care Teams, these should be in a CareTeam resource that may be linked to the CarePlan or EpisodeOfCare resources.\nMultiple GPs may be recorded against the patient for various reasons, such as a student that has his home GP listed along with the GP at university during the school semesters, or a \"fly-in/fly-out\" worker that has the onsite GP also included with his home GP to remain aware of medical issues.\n\nJurisdictions may decide that they can profile this down to 1 if desired, or 1 per type.", + "alias": [ + "careProvider" + ], + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization", + "http://hl7.org/fhir/StructureDefinition/Practitioner", + "http://hl7.org/fhir/StructureDefinition/PractitionerRole" + ] + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "v2", + "map": "PD1-4" + }, + { + "identity": "rim", + "map": "subjectOf.CareEvent.performer.AssignedEntity" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.managingOrganization", + "path": "Patient.managingOrganization", + "short": "Organization that is the custodian of the patient record", + "definition": "Organization that is the custodian of the patient record.", + "comment": "There is only one managing organization for a specific patient record. Other organizations will have their own Patient record, and may use the Link property to join the records together (or a Person resource which can include confidence ratings for the association).", + "requirements": "Need to know who recognizes this patient record, manages and updates it.", + "max": "1", + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization" + ] + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "scoper" + }, + { + "identity": "cda", + "map": ".providerOrganization" + } + ] + }, + { + "id": "Patient.link", + "path": "Patient.link", + "short": "Link to another patient resource that concerns the same actual person", + "definition": "Link to another patient resource that concerns the same actual patient.", + "comment": "There is no assumption that linked patient records have mutual links.", + "requirements": "There are multiple use cases: \n\n* Duplicate patient records due to the clerical errors associated with the difficulties of identifying humans consistently, and \n* Distribution of patient information across multiple servers.", + "type": [ + { + "code": "BackboneElement" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because it might not be the main Patient resource, and the referenced patient should be used instead of this Patient record. This is when the link.type value is 'replaced-by'", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "outboundLink" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.other", + "path": "Patient.link.other", + "short": "The other patient or related person resource that the link refers to", + "definition": "The other patient resource that the link refers to.", + "comment": "Referencing a RelatedPerson here removes the need to use a Person record to associate a Patient and RelatedPerson as the same individual.", + "min": 1, + "max": "1", + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy", + "valueBoolean": false + } + ], + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Patient", + "http://hl7.org/fhir/StructureDefinition/RelatedPerson" + ] + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "v2", + "map": "PID-3, MRG-1" + }, + { + "identity": "rim", + "map": "id" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + }, + { + "id": "Patient.link.type", + "path": "Patient.link.type", + "short": "replaced-by | replaces | refer | seealso", + "definition": "The type of link between this patient resource and another patient resource.", + "min": 1, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "LinkType" + } + ], + "strength": "required", + "description": "The type of link between this patient resource and another patient resource.", + "valueSet": "http://hl7.org/fhir/ValueSet/link-type|4.3.0" + }, + "mapping": [ + { + "identity": "rim", + "map": "typeCode" + }, + { + "identity": "cda", + "map": "n/a" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/SampleSourceGen/Models/Pokemon.StructureDefinition.json b/SampleSourceGen/Models/Pokemon.StructureDefinition.json index 1d7d771fc..70d5a6285 100644 --- a/SampleSourceGen/Models/Pokemon.StructureDefinition.json +++ b/SampleSourceGen/Models/Pokemon.StructureDefinition.json @@ -1,70 +1,755 @@ { - "resourceType": "StructureDefinition", - "id": "Pokemon", - "url": "http://hl7.org/fhir/StructureDefinition/Pokemon", - "version": "0.1", - "name": "Pokemon", - "status": "draft", - "fhirVersion": "4.3.0", - "kind": "resource", - "abstract": false, - "type": "Pokemon", - "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", - "derivation": "specialization", - "snapshot": { - "element": [ + "resourceType": "StructureDefinition", + "id": "Pokemon", + "url": "http://hl7.org/fhir/StructureDefinition/Pokemon", + "version": "0.1", + "name": "Pokemon", + "status": "draft", + "fhirVersion": "4.3.0", + "kind": "resource", + "abstract": false, + "type": "Pokemon", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/DomainResource", + "derivation": "specialization", + "snapshot": { + "element": [ + { + "id": "Pokemon", + "path": "Pokemon", + "short": "A resource with narrative, extensions, and contained resources", + "definition": "A resource that includes narrative, extensions, and contained resources.", + "min": 0, + "max": "*", + "base": { + "path": "Pokemon", + "min": 0, + "max": "*" + }, + "constraint": [ + { + "key": "dom-2", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL NOT contain nested Resources", + "expression": "contained.contained.empty()", + "xpath": "not(parent::f:contained and f:contained)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-4", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated", + "expression": "contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:versionId)) and not(exists(f:contained/*/f:meta/f:lastUpdated))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-3", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource", + "expression": "contained.where(((id.exists() and ('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url)))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(uri) = '#').exists()).not()).trace('unmatched', id).empty()", + "xpath": "not(exists(for $contained in f:contained return $contained[not(exists(parent::*/descendant::f:reference/@value=concat('#', $contained/*/f:id/@value)) or exists(descendant::f:reference[@value='#']))]))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice", + "valueBoolean": true + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation", + "valueMarkdown": "When a resource has no narrative, only systems that fully understand the data can display the resource to a human safely. Including a human readable representation in the resource makes for a much more robust eco-system and cheaper handling of resources by intermediary systems. Some ecosystems restrict distribution of resources to only those systems that do fully understand the resources, and as a consequence implementers may believe that the narrative is superfluous. However experience shows that such eco-systems often open up to new participants over time." + } + ], + "key": "dom-6", + "severity": "warning", + "human": "A resource should have narrative for robust management", + "expression": "text.`div`.exists()", + "xpath": "exists(f:text/h:div)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + }, + { + "key": "dom-5", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a security label", + "expression": "contained.meta.security.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:security))", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + } + ], + "mustSupport": false, + "isModifier": false, + "mapping": [ + { + "identity": "rim", + "map": "Entity. Role, or Act" + } + ] + }, + { + "id": "Pokemon.id", + "path": "Pokemon.id", + "short": "Logical id of this artifact", + "definition": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "comment": "The only time that a resource does not have an id is when it is being submitted to the server using a create operation.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type", + "valueUrl": "id" + } + ], + "code": "http://hl7.org/fhirpath/System.String" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true + }, + { + "id": "Pokemon.meta", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Pokemon.meta", + "short": "Metadata about the resource", + "definition": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.meta", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Meta" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Pokemon.implicitRules", + "path": "Pokemon.implicitRules", + "short": "A set of rules under which this content was created", + "definition": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "comment": "Asserting this rule set restricts the content to be only understood by a limited set of trading partners. This inherently limits the usefulness of the data in the long term. However, the existing health eco-system is highly fractured, and not yet ready to define, collect, and exchange data in a generally computable sense. Wherever possible, implementers and/or specification writers should avoid using this element. Often, when used, the URL is a reference to an implementation guide that defines these special rules as part of it's narrative along with other profiles, value sets, etc.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.implicitRules", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "uri" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because the implicit rules may provide additional knowledge about the resource that modifies it's meaning or interpretation", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Pokemon.language", + "path": "Pokemon.language", + "short": "Language of the resource content", + "definition": "The base language in which the resource is written.", + "comment": "Language is provided to support indexing and accessibility (typically, services such as text to speech use the language tag). The html language tag in the narrative applies to the narrative. The language tag on the resource may be used to specify the language of other presentations generated from the data in the resource. Not all the content has to be in the base language. The Resource.language should not be assumed to apply to the narrative automatically. If a language is specified, it should it also be specified on the div element in the html (see rules in HTML5 for information about the relationship between xml:lang and the html lang attribute).", + "min": 0, + "max": "1", + "base": { + "path": "Resource.language", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ { - "id": "Pokemon.name", - "path": "Pokemon.name", - "min": 1, - "max": "1", - "type": [ - { - "code": "string" - } - ] + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" }, { - "id": "Pokemon.nationalDexNo", - "path": "Pokemon.nationalDexNo", - "min": 0, - "max": "1", - "type": [ - { - "code": "integer" - } - ] + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" }, { - "id": "Pokemon.primaryType", - "path": "Pokemon.primaryType", - "min": 1, - "max": "1", - "type": [ - { - "code": "code" - } - ], - "binding": { - "strength": "required", - "valueSet": "http://pokemon.com/fhir/ValueSet/pokemontype" - } - }, + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "IETF language tag", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Pokemon.text", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Pokemon.text", + "short": "Text summary of the resource, for human interpretation", + "definition": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "comment": "Contained resources do not have narrative. Resources that are not contained SHOULD have a narrative. In some cases, a resource may only have text with little or no additional discrete data (as long as all minOccurs=1 elements are satisfied). This may be necessary for data from legacy systems where information is captured as a \"text blob\" or where text is additionally entered raw or narrated and encoded information is added later.", + "alias": [ + "narrative", + "html", + "xhtml", + "display" + ], + "min": 0, + "max": "1", + "base": { + "path": "DomainResource.text", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Narrative" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + }, + { + "identity": "rim", + "map": "Act.text?" + } + ] + }, + { + "id": "Pokemon.contained", + "path": "Pokemon.contained", + "short": "Contained, inline Resources", + "definition": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, and nor can they have their own independent transaction scope.", + "comment": "This should never be done when the content can be identified properly, as once identification is lost, it is extremely difficult (and context dependent) to restore it again. Contained resources may have profiles and tags In their meta elements, but SHALL NOT have security labels.", + "alias": [ + "inline resources", + "anonymous resources", + "contained resources" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.contained", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Resource" + } + ], + "constraint": [ + { + "key": "dom-r4b", + "severity": "warning", + "human": "Containing new R4B resources within R4 resources may cause interoperability issues if instances are shared with R4 systems", + "expression": "($this is Citation or $this is Evidence or $this is EvidenceReport or $this is EvidenceVariable or $this is MedicinalProductDefinition or $this is PackagedProductDefinition or $this is AdministrableProductDefinition or $this is Ingredient or $this is ClinicalUseDefinition or $this is RegulatedAuthorization or $this is SubstanceDefinition or $this is SubscriptionStatus or $this is SubscriptionTopic) implies (%resource is Citation or %resource is Evidence or %resource is EvidenceReport or %resource is EvidenceVariable or %resource is MedicinalProductDefinition or %resource is PackagedProductDefinition or %resource is AdministrableProductDefinition or %resource is Ingredient or %resource is ClinicalUseDefinition or %resource is RegulatedAuthorization or %resource is SubstanceDefinition or %resource is SubscriptionStatus or %resource is SubscriptionTopic)", + "xpath": "not(f:Citation|f:Evidence|f:EvidenceReport|f:EvidenceVariable|f:MedicinalProductDefinition|f:PackagedProductDefinition|f:AdministrableProductDefinition|f:Ingredient|f:ClinicalUseDefinition|f:RegulatedAuthorization|f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic) or not(parent::f:Citation|parent::f:Evidence|parent::f:EvidenceReport|parent::f:EvidenceVariable|parent::f:MedicinalProductDefinition|parent::f:PackagedProductDefinition|parent::f:AdministrableProductDefinition|parent::f:Ingredient|parent::f:ClinicalUseDefinition|parent::f:RegulatedAuthorization|parent::f:SubstanceDefinition|f:SubscriptionStatus|f:SubscriptionTopic)", + "source": "http://hl7.org/fhir/StructureDefinition/DomainResource" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Entity. Role, or Act" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Pokemon.extension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Pokemon.extension", + "slicing": { + "discriminator": [ { - "id": "Pokemon.secondaryType", - "path": "Pokemon.secondaryType", - "min": 0, - "max": "1", - "type": [ - { - "code": "code" - } - ], - "binding": { - "strength": "required", - "valueSet": "http://pokemon.com/fhir/ValueSet/pokemontype" - } + "type": "value", + "path": "url" } + ], + "description": "Extensions are always sliced by (at least) url", + "rules": "open" + }, + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Pokemon.modifierExtension", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status", + "valueCode": "normative" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version", + "valueCode": "4.0.0" + } + ], + "path": "Pokemon.modifierExtension", + "slicing": { + "discriminator": [ + { + "type": "value", + "path": "url" + } + ], + "description": "Extensions are always sliced by (at least) url", + "rules": "open" + }, + "short": "Extensions that cannot be ignored", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + }, + { + "key": "ext-1", + "severity": "error", + "human": "Must have either extensions or value[x], not both", + "expression": "extension.exists() != value.exists()", + "xpath": "exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])", + "source": "http://hl7.org/fhir/StructureDefinition/Extension" + } + ], + "mustSupport": false, + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the resource that contains them", + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + }, + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Pokemon.name", + "path": "Pokemon.name", + "short": "Primitive Type string", + "definition": "A sequence of Unicode characters", + "comment": "Note that FHIR strings SHALL NOT exceed 1MB in size", + "min": 1, + "max": "1", + "base": { + "path": "Pokemon.name", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "string" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Pokemon.nationalDexNo", + "path": "Pokemon.nationalDexNo", + "short": "Primitive Type integer", + "definition": "A whole number", + "comment": "32 bit number; for values larger than this, use decimal", + "min": 0, + "max": "1", + "base": { + "path": "Pokemon.nationalDexNo", + "max": "1" + }, + "type": [ + { + "code": "integer" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Pokemon.primaryType", + "path": "Pokemon.primaryType", + "short": "Primitive Type code", + "definition": "A string which has at least one character and no leading or trailing whitespace and where there is no whitespace other than single spaces in the contents", + "comment": "Note that FHIR strings SHALL NOT exceed 1MB in size", + "min": 1, + "max": "1", + "base": { + "path": "Pokemon.primaryType", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "binding": { + "strength": "required", + "valueSet": "http://pokemon.com/fhir/ValueSet/pokemontype" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Pokemon.secondaryType", + "path": "Pokemon.secondaryType", + "short": "Primitive Type code", + "definition": "A string which has at least one character and no leading or trailing whitespace and where there is no whitespace other than single spaces in the contents", + "comment": "Note that FHIR strings SHALL NOT exceed 1MB in size", + "min": 0, + "max": "1", + "base": { + "path": "Pokemon.secondaryType", + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "condition": [ + "ele-1" + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children unless an empty Parameters resource", + "expression": "hasValue() or (children().count() > id.count()) or $this is Parameters", + "xpath": "@value|f:*|h:div|self::f:Parameters", + "source": "http://hl7.org/fhir/StructureDefinition/Element" + } + ], + "binding": { + "strength": "required", + "valueSet": "http://pokemon.com/fhir/ValueSet/pokemontype" + }, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + } + ] + }, + "differential": { + "element": [ + { + "id": "Pokemon.name", + "path": "Pokemon.name", + "min": 1, + "max": "1", + "type": [ + { + "code": "string" + } + ] + }, + { + "id": "Pokemon.nationalDexNo", + "path": "Pokemon.nationalDexNo", + "max": "1", + "type": [ + { + "code": "integer" + } ] - } -} + }, + { + "id": "Pokemon.primaryType", + "path": "Pokemon.primaryType", + "min": 1, + "max": "1", + "type": [ + { + "code": "code" + } + ], + "binding": { + "strength": "required", + "valueSet": "http://pokemon.com/fhir/ValueSet/pokemontype" + } + }, + { + "id": "Pokemon.secondaryType", + "path": "Pokemon.secondaryType", + "max": "1", + "type": [ + { + "code": "code" + } + ], + "binding": { + "strength": "required", + "valueSet": "http://pokemon.com/fhir/ValueSet/pokemontype" + } + } + ] + } +} \ No newline at end of file From 2153ef3e9abf70201800022820cfe2797e55d8a9 Mon Sep 17 00:00:00 2001 From: almostchristian Date: Tue, 17 Oct 2023 14:00:34 +0800 Subject: [PATCH 11/15] Improve source gen error messages and added diagnostics --- TestSourceGen/Program.cs | 3 +- .../DiagnosticDescriptors.cs | 16 ++++++ .../Emitter.cs | 25 +++++---- .../Parsing/Parser.cs | 53 ++++++++++++------- .../Parsing/ResourcePartialClass.cs | 6 ++- .../Language/CSharpFirely2IG.cs | 3 -- 6 files changed, 72 insertions(+), 34 deletions(-) diff --git a/TestSourceGen/Program.cs b/TestSourceGen/Program.cs index 608705a3e..243fee651 100644 --- a/TestSourceGen/Program.cs +++ b/TestSourceGen/Program.cs @@ -1,9 +1,10 @@ // See https://aka.ms/new-console-template for more information +using Microsoft.CodeAnalysis; using Microsoft.Health.Fhir.SourceGenerator; using Microsoft.Health.Fhir.SourceGenerator.Parsing; -var resourceClass = new ResourcePartialClass(typeof(Program).Namespace!, "Patient", "Patient.StructureDefinition.json", Array.Empty()); +var resourceClass = new ResourcePartialClass(Location.None, typeof(Program).Namespace!, "Patient", "Patient.StructureDefinition.json", Array.Empty()); var emitter = new Emitter(resourceClass, diag => Console.Error.WriteLine(diag.GetMessage())); diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/DiagnosticDescriptors.cs b/src/Microsoft.Health.Fhir.SourceGenerator/DiagnosticDescriptors.cs index b591c5195..46ec4a223 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/DiagnosticDescriptors.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/DiagnosticDescriptors.cs @@ -43,4 +43,20 @@ internal static class DiagnosticDescriptors "FhirSourceGenerator", DiagnosticSeverity.Info, true); + + public static readonly DiagnosticDescriptor ResourceNameMismatch = new( + "FHIRGEN006", + "FHIR Resource name mismatch", + "StructureDefinition with name '{0}' mismatches with the partial class '{1}'.", + "FhirSourceGenerator", + DiagnosticSeverity.Error, + true); + + public static readonly DiagnosticDescriptor UnableToResolveFilePath = new( + "FHIRGEN007", + "FHIR Resource file not found", + "Unable to find FHIR resource file at path '{0}'.", + "FhirSourceGenerator", + DiagnosticSeverity.Error, + true); } diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Emitter.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Emitter.cs index b31e7e03b..bd6b3bbf5 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/Emitter.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Emitter.cs @@ -17,14 +17,14 @@ internal class Emitter private readonly IFhirConverter _fhirConverter = new FromFhirExpando(); private readonly FhirVersionInfo _fhirInfo = new FhirVersionInfo(FhirPackageCommon.FhirSequenceEnum.R4B); private readonly ResourcePartialClass _resource; - private readonly Action _reportError; + private readonly Action _report; public Emitter( ResourcePartialClass resource, - Action reportError) + Action report) { _resource = resource; - _reportError = reportError; + _report = report; } public string? Emit() @@ -64,11 +64,11 @@ static bool TryGetFhirTerminology(FhirVersionInfo m, string key, out object? val } catch (ReflectionTypeLoadException rex) { - _reportError(Diagnostic.Create(DiagnosticDescriptors.TypeLoaderException, Location.None, rex.LoaderExceptions)); + _report(Diagnostic.Create(DiagnosticDescriptors.TypeLoaderException, Location.None, rex.LoaderExceptions)); } catch (Exception ex) { - _reportError(Diagnostic.Create(DiagnosticDescriptors.UnhandledException, Location.None, ex)); + _report(Diagnostic.Create(DiagnosticDescriptors.UnhandledException, Location.None, ex)); } return null; @@ -89,11 +89,11 @@ private void ProcessTerminologyArtifacts( var model = ProcessFile(path, fhirInfo, _fhirConverter, modelCollectionLocator, out var fileName, out var canonical, out var artifactClass); if (model == null || (artifactClass != FhirArtifactClassEnum.CodeSystem && artifactClass != FhirArtifactClassEnum.ValueSet)) { - _reportError(Diagnostic.Create(DiagnosticDescriptors.FailedArtifactDef, Location.None, path, "CodeSystem or ValueSet")); + _report(Diagnostic.Create(DiagnosticDescriptors.FailedArtifactDef, Location.None, path, "CodeSystem or ValueSet")); continue; } - _reportError(Diagnostic.Create(DiagnosticDescriptors.ProcessSuccess, Location.None, path, canonical, artifactClass, fhirInfo.Resources.Count)); + _report(Diagnostic.Create(DiagnosticDescriptors.ProcessSuccess, Location.None, path, canonical, artifactClass, fhirInfo.Resources.Count)); } } @@ -104,11 +104,16 @@ private void ProcessTerminologyArtifacts( var complex = ProcessFile(structureDef, fhirInfo, _fhirConverter, m => m.Resources, out var id, out var canonical, out var artifactClass); if (complex == null || artifactClass != FhirArtifactClassEnum.Resource) { - _reportError(Diagnostic.Create(DiagnosticDescriptors.FailedArtifactDef, Location.None, structureDef, FhirArtifactClassEnum.Resource)); + _report(Diagnostic.Create(DiagnosticDescriptors.FailedArtifactDef, Location.None, structureDef, FhirArtifactClassEnum.Resource)); + return null; + } + else if (complex.Name != _resource.Name) + { + _report(Diagnostic.Create(DiagnosticDescriptors.ResourceNameMismatch, _resource.Location, complex.Name, _resource.Name)); return null; } - _reportError(Diagnostic.Create(DiagnosticDescriptors.ProcessSuccess, Location.None, structureDef, canonical, artifactClass, fhirInfo.Resources.Count)); + _report(Diagnostic.Create(DiagnosticDescriptors.ProcessSuccess, Location.None, structureDef, canonical, artifactClass, fhirInfo.Resources.Count)); return GenerateFhirResourceSource(fhirInfo, complex, structureDef); @@ -124,7 +129,7 @@ private void ProcessTerminologyArtifacts( if (memoryStream.Length == 0) { - _reportError(Diagnostic.Create(DiagnosticDescriptors.FailedToGenerate, Location.None, originalFilePath)); + _report(Diagnostic.Create(DiagnosticDescriptors.FailedToGenerate, Location.None, originalFilePath)); return null; } diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs index 66c67fc9c..785322ff7 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs @@ -58,6 +58,7 @@ internal IReadOnlyList GetResourcePartialClasses(IEnumerab string? structureDefPath = null; string[] terminologies = Array.Empty(); + Location? location = null; foreach (AttributeListSyntax mal in classDec.AttributeLists) { @@ -103,8 +104,8 @@ internal IReadOnlyList GetResourcePartialClasses(IEnumerab switch (items.Length) { case 1: - // GenerateServiceRegistration(string configurationSection) - structureDefPath = (string)GetItem(items[0])!; + var value = GetItem(items[0]) as string; + structureDefPath = ResolvePath(value); break; default: @@ -132,7 +133,13 @@ internal IReadOnlyList GetResourcePartialClasses(IEnumerab { case "TerminologyResources": var values = (ImmutableArray)GetItem(value)!; - terminologies = values.Select(x => x.Value?.ToString()).Where(x => !string.IsNullOrEmpty(x)).ToArray()!; + var testValues = values.Select(x => x.Value?.ToString()).Where(x => !string.IsNullOrEmpty(x)).ToArray()!; + terminologies = new string[testValues.Length]; + for (int i = 0; i < testValues.Length; i++) + { + terminologies[i] = ResolvePath(testValues[i])!; + } + break; } } @@ -145,7 +152,31 @@ internal IReadOnlyList GetResourcePartialClasses(IEnumerab break; } + location = ma.GetLocation(); static object? GetItem(TypedConstant arg) => arg.Kind == TypedConstantKind.Array ? arg.Values : arg.Value; + + string? ResolvePath(string? path) + { + if (path == null) + { + return null; + } + + path = Path.Combine(path.Split('/', '\\')); + string found = _context.AdditionalFiles.Where(x => x.Path.EndsWith(path)).Select(x => x.Path).FirstOrDefault(); + if (found == null && projectDir != null) + { + found = Path.Combine(projectDir, path); + } + + if (!File.Exists(found)) + { + hasMisconfiguredInput = true; + _reportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.UnableToResolveFilePath, ma.GetLocation(), found)); + } + + return found; + } } } } @@ -183,21 +214,7 @@ potentialNamespaceParent is not NamespaceDeclarationSyntax && } } - result.Add(new ResourcePartialClass(nspace, classDecSymbol.Name, ResolvePath(structureDefPath), terminologies.Select(ResolvePath).ToArray())); - - string ResolvePath(string path) - { - path = Path.Combine(path.Split('/', '\\')); - var found = _context.AdditionalFiles.Where(x => x.Path.EndsWith(path)).Select(x => x.Path).FirstOrDefault(); - if (found == null && projectDir != null) - { - found = Path.Combine(projectDir, path); - } - - Debug.Assert(File.Exists(found), $"File {found} does not exist"); - - return found; - } + result.Add(new ResourcePartialClass(location, nspace, classDecSymbol.Name, structureDefPath, terminologies)); } } } diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/ResourcePartialClass.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/ResourcePartialClass.cs index 69b587a30..96626bf9b 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/ResourcePartialClass.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/ResourcePartialClass.cs @@ -1,3 +1,5 @@ -namespace Microsoft.Health.Fhir.SourceGenerator.Parsing; +using Microsoft.CodeAnalysis; -internal record class ResourcePartialClass(string Namespace, string Name, string StructureDefinitionPath, string[] TerminologyResourcePaths); +namespace Microsoft.Health.Fhir.SourceGenerator.Parsing; + +internal record class ResourcePartialClass(Location Location, string Namespace, string Name, string StructureDefinitionPath, string[] TerminologyResourcePaths); diff --git a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs index 868fbd36a..7667c65e4 100644 --- a/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs +++ b/src/Microsoft.Health.Fhir.SpecManager/Language/CSharpFirely2IG.cs @@ -3444,9 +3444,6 @@ private void WriteGenerationComment(ExportStreamWriter writer = null) writer.WriteLineIndented("// "); writer.WriteLineIndented($"// Contents of: {_info.PackageName} version: {_info.VersionString}"); -#if !DEBUG - writer.WriteLineIndented($"// Generated by {_headerUserName} on {_headerGenerationDateTime}"); -#endif if ((_options.ExportList != null) && _options.ExportList.Any()) { string restrictions = string.Join("|", _options.ExportList); From cefe1919cacd974b2d255801c5c899fcc4ec5f95 Mon Sep 17 00:00:00 2001 From: almostchristian Date: Mon, 30 Oct 2023 14:32:36 +0800 Subject: [PATCH 12/15] Added readme --- .../Microsoft.Health.Fhir.CodeGeneration.csproj | 4 ++++ .../README.md | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/Microsoft.Health.Fhir.CodeGeneration/README.md diff --git a/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj index 20c631bab..9d93e8b56 100644 --- a/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj +++ b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj @@ -30,6 +30,10 @@
+ + + + Date: Mon, 30 Oct 2023 14:34:01 +0800 Subject: [PATCH 13/15] Change version to 1.0.0-alpha.1 --- .../Microsoft.Health.Fhir.CodeGeneration.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj index 9d93e8b56..b0da388fc 100644 --- a/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj +++ b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj @@ -7,7 +7,7 @@ true true analyzers\cs - 0.1.0-beta.2 + 1.0.0-alpha.1 From 990f503d7b7b415c152f0a6b88866aa71ead5ea8 Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Tue, 14 Nov 2023 10:54:44 +0800 Subject: [PATCH 14/15] Change namespace to Synapxe from Microsoft.Health. Add azure build pipeline --- SampleSourceGen/Education.cs | 2 +- SampleSourceGen/Models/Patient.cs | 2 +- SampleSourceGen/Models/Pokemon.cs | 2 +- ci-azure-pipelines.yml | 28 +++++++++++++++++++ nuget.config | 13 +++++++++ .../GeneratedFhirAttribute.cs | 2 +- ...icrosoft.Health.Fhir.CodeGeneration.csproj | 4 ++- .../Parsing/Parser.cs | 2 +- 8 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 ci-azure-pipelines.yml create mode 100644 nuget.config diff --git a/SampleSourceGen/Education.cs b/SampleSourceGen/Education.cs index bdd540b4b..d7685b174 100644 --- a/SampleSourceGen/Education.cs +++ b/SampleSourceGen/Education.cs @@ -1,4 +1,4 @@ -using Microsoft.Health.Fhir.CodeGeneration; +using Synapxe.Fhir.CodeGeneration; namespace SampleSourceGen; diff --git a/SampleSourceGen/Models/Patient.cs b/SampleSourceGen/Models/Patient.cs index 046a4f35a..211d236f1 100644 --- a/SampleSourceGen/Models/Patient.cs +++ b/SampleSourceGen/Models/Patient.cs @@ -1,4 +1,4 @@ -using Microsoft.Health.Fhir.CodeGeneration; +using Synapxe.Fhir.CodeGeneration; namespace SampleSourceGen.Models; diff --git a/SampleSourceGen/Models/Pokemon.cs b/SampleSourceGen/Models/Pokemon.cs index daca67379..7954193b8 100644 --- a/SampleSourceGen/Models/Pokemon.cs +++ b/SampleSourceGen/Models/Pokemon.cs @@ -1,4 +1,4 @@ -using Microsoft.Health.Fhir.CodeGeneration; +using Synapxe.Fhir.CodeGeneration; namespace SampleSourceGen.Models; diff --git a/ci-azure-pipelines.yml b/ci-azure-pipelines.yml new file mode 100644 index 000000000..c456d1d18 --- /dev/null +++ b/ci-azure-pipelines.yml @@ -0,0 +1,28 @@ + +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +name: NricValidator-CI-$(Date:yy)$(DayOfYear)$(Rev:.r) + +pool: + name: 'HIP-LNX-SSP' + +variables: + buildConfiguration: 'Release' + versionSuffix: '-alpha-$(Build.BuildNumber)' + +steps: +- task: NuGetAuthenticate@1 + inputs: + nuGetServiceConnections: 'HIP-Nexus2' +- script: dotnet restore --no-cache --configfile nuget.config + displayName: 'Restore nuget' +- script: dotnet build fhir-codegen.sln --no-restore --configuration $(buildConfiguration) /p:VERSION_SUFFIX=$(versionSuffix) /p:GIT_VERSION=$(Build.SourceVersion) + displayName: 'dotnet build framework $(buildConfiguration)' +- task: PublishPipelineArtifact@1 + displayName: Publish Nuget packages + inputs: + targetPath: '$(Build.SourcesDirectory)/packages' + artifact: '$(Build.BuildNumber)' + publishLocation: 'pipeline' diff --git a/nuget.config b/nuget.config new file mode 100644 index 000000000..b3cc38aa6 --- /dev/null +++ b/nuget.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs b/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs index fb2f6e03a..027bd3202 100644 --- a/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs +++ b/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs @@ -1,6 +1,6 @@ using System; -namespace Microsoft.Health.Fhir.CodeGeneration; +namespace Synapxe.Fhir.CodeGeneration; [AttributeUsage(AttributeTargets.Class)] public class GeneratedFhirAttribute : Attribute diff --git a/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj index b0da388fc..b1222c048 100644 --- a/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj +++ b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj @@ -7,7 +7,9 @@ true true analyzers\cs - 1.0.0-alpha.1 + 1.0.0$(VERSION_SUFFIX) + Synapxe.Fhir.CodeGeneration + $(MSBuildThisFileDirectory)..\..\packages diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs index 785322ff7..a161c7d35 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs @@ -12,7 +12,7 @@ namespace Microsoft.Health.Fhir.SourceGenerator.Parsing; internal class Parser { - internal const string GeneratedFhirAttributeName = "Microsoft.Health.Fhir.CodeGeneration.GeneratedFhirAttribute"; + internal const string GeneratedFhirAttributeName = "Synapxe.Fhir.CodeGeneration.GeneratedFhirAttribute"; private readonly GeneratorExecutionContext _context; private readonly Action _reportDiagnostic; private readonly CancellationToken _cancellationToken; From 4c3b32c21f3d6bc1bfc18b17053d84ad45e9f0db Mon Sep 17 00:00:00 2001 From: Christian Donn Sarmago Relacion Date: Tue, 14 Nov 2023 10:58:47 +0800 Subject: [PATCH 15/15] Revert "Change namespace to Synapxe from Microsoft.Health." This reverts commit 990f503d7b7b415c152f0a6b88866aa71ead5ea8. --- SampleSourceGen/Education.cs | 2 +- SampleSourceGen/Models/Patient.cs | 2 +- SampleSourceGen/Models/Pokemon.cs | 2 +- ci-azure-pipelines.yml | 28 ------------------- nuget.config | 13 --------- .../GeneratedFhirAttribute.cs | 2 +- ...icrosoft.Health.Fhir.CodeGeneration.csproj | 4 +-- .../Parsing/Parser.cs | 2 +- 8 files changed, 6 insertions(+), 49 deletions(-) delete mode 100644 ci-azure-pipelines.yml delete mode 100644 nuget.config diff --git a/SampleSourceGen/Education.cs b/SampleSourceGen/Education.cs index d7685b174..bdd540b4b 100644 --- a/SampleSourceGen/Education.cs +++ b/SampleSourceGen/Education.cs @@ -1,4 +1,4 @@ -using Synapxe.Fhir.CodeGeneration; +using Microsoft.Health.Fhir.CodeGeneration; namespace SampleSourceGen; diff --git a/SampleSourceGen/Models/Patient.cs b/SampleSourceGen/Models/Patient.cs index 211d236f1..046a4f35a 100644 --- a/SampleSourceGen/Models/Patient.cs +++ b/SampleSourceGen/Models/Patient.cs @@ -1,4 +1,4 @@ -using Synapxe.Fhir.CodeGeneration; +using Microsoft.Health.Fhir.CodeGeneration; namespace SampleSourceGen.Models; diff --git a/SampleSourceGen/Models/Pokemon.cs b/SampleSourceGen/Models/Pokemon.cs index 7954193b8..daca67379 100644 --- a/SampleSourceGen/Models/Pokemon.cs +++ b/SampleSourceGen/Models/Pokemon.cs @@ -1,4 +1,4 @@ -using Synapxe.Fhir.CodeGeneration; +using Microsoft.Health.Fhir.CodeGeneration; namespace SampleSourceGen.Models; diff --git a/ci-azure-pipelines.yml b/ci-azure-pipelines.yml deleted file mode 100644 index c456d1d18..000000000 --- a/ci-azure-pipelines.yml +++ /dev/null @@ -1,28 +0,0 @@ - -# Start with a minimal pipeline that you can customize to build and deploy your code. -# Add steps that build, run tests, deploy, and more: -# https://aka.ms/yaml - -name: NricValidator-CI-$(Date:yy)$(DayOfYear)$(Rev:.r) - -pool: - name: 'HIP-LNX-SSP' - -variables: - buildConfiguration: 'Release' - versionSuffix: '-alpha-$(Build.BuildNumber)' - -steps: -- task: NuGetAuthenticate@1 - inputs: - nuGetServiceConnections: 'HIP-Nexus2' -- script: dotnet restore --no-cache --configfile nuget.config - displayName: 'Restore nuget' -- script: dotnet build fhir-codegen.sln --no-restore --configuration $(buildConfiguration) /p:VERSION_SUFFIX=$(versionSuffix) /p:GIT_VERSION=$(Build.SourceVersion) - displayName: 'dotnet build framework $(buildConfiguration)' -- task: PublishPipelineArtifact@1 - displayName: Publish Nuget packages - inputs: - targetPath: '$(Build.SourcesDirectory)/packages' - artifact: '$(Build.BuildNumber)' - publishLocation: 'pipeline' diff --git a/nuget.config b/nuget.config deleted file mode 100644 index b3cc38aa6..000000000 --- a/nuget.config +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs b/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs index 027bd3202..fb2f6e03a 100644 --- a/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs +++ b/src/Microsoft.Health.Fhir.CodeGeneration/GeneratedFhirAttribute.cs @@ -1,6 +1,6 @@ using System; -namespace Synapxe.Fhir.CodeGeneration; +namespace Microsoft.Health.Fhir.CodeGeneration; [AttributeUsage(AttributeTargets.Class)] public class GeneratedFhirAttribute : Attribute diff --git a/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj index b1222c048..b0da388fc 100644 --- a/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj +++ b/src/Microsoft.Health.Fhir.CodeGeneration/Microsoft.Health.Fhir.CodeGeneration.csproj @@ -7,9 +7,7 @@ true true analyzers\cs - 1.0.0$(VERSION_SUFFIX) - Synapxe.Fhir.CodeGeneration - $(MSBuildThisFileDirectory)..\..\packages + 1.0.0-alpha.1 diff --git a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs index a161c7d35..785322ff7 100644 --- a/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs +++ b/src/Microsoft.Health.Fhir.SourceGenerator/Parsing/Parser.cs @@ -12,7 +12,7 @@ namespace Microsoft.Health.Fhir.SourceGenerator.Parsing; internal class Parser { - internal const string GeneratedFhirAttributeName = "Synapxe.Fhir.CodeGeneration.GeneratedFhirAttribute"; + internal const string GeneratedFhirAttributeName = "Microsoft.Health.Fhir.CodeGeneration.GeneratedFhirAttribute"; private readonly GeneratorExecutionContext _context; private readonly Action _reportDiagnostic; private readonly CancellationToken _cancellationToken;