diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java index 7b211b8eb..58fcd84db 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java @@ -435,5 +435,13 @@ public class ContextUtilities implements ProfileKnowledgeProvider { return null; } + public boolean isAbstractType(String typeName) { + StructureDefinition sd = context.fetchTypeDefinition(typeName); + if (sd != null) { + return sd.getAbstract(); + } + return false; + } + } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Constants.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Constants.java index 8932e3cc6..898624628 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Constants.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Constants.java @@ -43,5 +43,6 @@ public class Constants { public final static String VERSION_MM = "5.0"; public final static String DATE = "Thu, Mar 23, 2023 19:59+1100"; public final static String URI_REGEX = "((http|https):\\/\\/([A-Za-z0-9\\\\\\.\\:\\%\\$\\-]*\\/)*?)?(Account|ActivityDefinition|ActorDefinition|AdministrableProductDefinition|AdverseEvent|AllergyIntolerance|Appointment|AppointmentResponse|ArtifactAssessment|AuditEvent|Basic|Binary|BiologicallyDerivedProduct|BiologicallyDerivedProductDispense|BodyStructure|Bundle|CapabilityStatement|CarePlan|CareTeam|ChargeItem|ChargeItemDefinition|Citation|Claim|ClaimResponse|ClinicalImpression|ClinicalUseDefinition|CodeSystem|Communication|CommunicationRequest|CompartmentDefinition|Composition|ConceptMap|Condition|ConditionDefinition|Consent|Contract|Coverage|CoverageEligibilityRequest|CoverageEligibilityResponse|DetectedIssue|Device|DeviceAssociation|DeviceDefinition|DeviceDispense|DeviceMetric|DeviceRequest|DeviceUsage|DiagnosticReport|DocumentReference|Encounter|EncounterHistory|Endpoint|EnrollmentRequest|EnrollmentResponse|EpisodeOfCare|EventDefinition|Evidence|EvidenceReport|EvidenceVariable|ExampleScenario|ExplanationOfBenefit|FamilyMemberHistory|Flag|FormularyItem|GenomicStudy|Goal|GraphDefinition|Group|GuidanceResponse|HealthcareService|ImagingSelection|ImagingStudy|Immunization|ImmunizationEvaluation|ImmunizationRecommendation|ImplementationGuide|Ingredient|InsurancePlan|InventoryItem|InventoryReport|Invoice|Library|Linkage|List|Location|ManufacturedItemDefinition|Measure|MeasureReport|Medication|MedicationAdministration|MedicationDispense|MedicationKnowledge|MedicationRequest|MedicationStatement|MedicinalProductDefinition|MessageDefinition|MessageHeader|MolecularSequence|NamingSystem|NutritionIntake|NutritionOrder|NutritionProduct|Observation|ObservationDefinition|OperationDefinition|OperationOutcome|Organization|OrganizationAffiliation|PackagedProductDefinition|Parameters|Patient|PaymentNotice|PaymentReconciliation|Permission|Person|PlanDefinition|Practitioner|PractitionerRole|Procedure|Provenance|Questionnaire|QuestionnaireResponse|RegulatedAuthorization|RelatedPerson|RequestOrchestration|Requirements|ResearchStudy|ResearchSubject|RiskAssessment|Schedule|SearchParameter|ServiceRequest|Slot|Specimen|SpecimenDefinition|StructureDefinition|StructureMap|Subscription|SubscriptionStatus|SubscriptionTopic|Substance|SubstanceDefinition|SubstanceNucleicAcid|SubstancePolymer|SubstanceProtein|SubstanceReferenceInformation|SubstanceSourceMaterial|SupplyDelivery|SupplyRequest|Task|TerminologyCapabilities|TestPlan|TestReport|TestScript|Transport|ValueSet|VerificationResult|VisionPrescription)\\/[A-Za-z0-9\\-\\.]{1,64}(\\/_history\\/[A-Za-z0-9\\-\\.]{1,64})?"; + public static final String NS_FHIR_ROOT = "http://hl7.org/fhir"; public static final String NS_CDA_ROOT = "http://hl7.org/cda/stds/core"; } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/TypeDetails.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/TypeDetails.java index 5b6609c19..72340c0e6 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/TypeDetails.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/TypeDetails.java @@ -62,12 +62,20 @@ public class TypeDetails { public static final Set FP_NUMBERS = new HashSet(Arrays.asList(FP_Integer, FP_Decimal)); public static class ProfiledType { + @Override + public String toString() { + return uri; + } + private String uri; private List profiles; // or, not and private List bindings; public ProfiledType(String n) { - uri = ns(n); + uri = ns(n); + if (uri.equals("http://hl7.org/fhir/StructureDefinition/CDA")) { + System.out.println("!"); // #FIXME + } } public String getUri() { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java index e34e3b2fb..25f6b78b8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java @@ -3308,7 +3308,8 @@ public class FHIRPathEngine { } case As : { checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String)); - TypeDetails td = new TypeDetails(CollectionStatus.SINGLETON, exp.getParameters().get(0).getName()); + String tn = checkType(focus, exp); + TypeDetails td = new TypeDetails(CollectionStatus.SINGLETON, tn); if (td.typesHaveTargets()) { td.addTargets(focus.getTargets()); } @@ -3316,10 +3317,7 @@ public class FHIRPathEngine { } case OfType : { checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String)); - String tn = exp.getParameters().get(0).getName(); - if (typeCastIsImpossible(focus, tn)) { - typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_OFTYPE_IMPOSSIBLE, focus.describeMin(), tn, exp.toString()), I18nConstants.FHIRPATH_OFTYPE_IMPOSSIBLE)); - } + String tn = checkType(focus, exp); TypeDetails td = new TypeDetails(CollectionStatus.SINGLETON, tn); if (td.typesHaveTargets()) { td.addTargets(focus.getTargets()); @@ -3639,6 +3637,27 @@ public class FHIRPathEngine { throw new Error("not Implemented yet"); } + private String checkType(TypeDetails focus, ExpressionNode exp) { + String tn; + if (exp.getParameters().get(0).getInner() != null) { + tn = exp.getParameters().get(0).getName()+"."+exp.getParameters().get(0).getInner().getName(); + } else { + tn = "FHIR."+exp.getParameters().get(0).getName(); + } + if (tn.startsWith("System.")) { + tn = tn.substring(7); + } else if (tn.startsWith("FHIR.")) { + tn = Utilities.pathURL(Constants.NS_FHIR_ROOT, "StructureDefinition", tn.substring(5)); + } else if (tn.startsWith("CDA.")) { + tn = Utilities.pathURL(Constants.NS_CDA_ROOT, "StructureDefinition", tn.substring(4)); + } + + if (typeCastIsImpossible(focus, tn)) { + typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_OFTYPE_IMPOSSIBLE, focus.describeMin(), tn, exp.toString()), I18nConstants.FHIRPATH_OFTYPE_IMPOSSIBLE)); + } + return tn; + } + private boolean typeCastIsImpossible(TypeDetails focus, String tn) { return !focus.hasType(tn); } @@ -5988,7 +6007,7 @@ public class FHIRPathEngine { for (TypeRefComponent t : ed.getType()) { if (t.hasCode() && t.getCodeElement().hasValue()) { String tn = null; - if (t.getCode().equals("Element") || t.getCode().equals("BackboneElement")) { + if (Utilities.existsInList(t.getCode(), "Element", "BackboneElement", "Base") || cu.isAbstractType(t.getCode())) { tn = sdi.getType()+"#"+ed.getPath(); } else { tn = t.getCode(); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java index 26a00b04b..c87535cd0 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java @@ -560,7 +560,12 @@ public class StructureDefinitionValidator extends BaseValidator { if (Utilities.existsInList(rootPath, context.getResourceNames())) { fpe.checkOnTypes(vc, rootPath, types, fpe.parse(exp), warnings); } else { - fpe.checkOnTypes(vc, "DomainResource", types, fpe.parse(exp), warnings); + StructureDefinition sd = context.fetchTypeDefinition(rootPath); + if (sd != null) { + fpe.checkOnTypes(vc, rootPath, types, fpe.parse(exp), warnings); + } else { + fpe.checkOnTypes(vc, "DomainResource", types, fpe.parse(exp), warnings); + } } for (IssueMessage s : warnings) { warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, s.getId(), false, key+": "+s.getMessage());