internal OperationOutcome ValidateConstraints(ElementDefinition definition, IElementNavigator instance)
        {
            // Make sure FHIR extensions are installed in FP compiler
            PocoNavigatorExtensions.PrepareFhirSymbolTableFunctions();

            var outcome = new OperationOutcome();

            if (Settings.SkipConstraintValidation)
            {
                return(outcome);
            }

            var context = ScopeTracker.ResourceContext(instance);

            // <constraint>
            //  <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-expression">
            //    <valueString value="reference.startsWith('#').not() or (reference.substring(1).trace('url') in %resource.contained.id.trace('ids'))"/>
            //  </extension>
            //  <key value="ref-1"/>
            //  <severity value="error"/>
            //  <human value="SHALL have a local reference if the resource is provided inline"/>
            //  <xpath value="not(starts-with(f:reference/@value, &#39;#&#39;)) 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, &#39;#&#39;)]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, &#39;#&#39;)])"/>
            //</constraint>
            //

            foreach (var constraintElement in definition.Constraint)
            {
                var fpExpression = constraintElement.GetFhirPathConstraint();

                if (fpExpression != null)
                {
                    try
                    {
                        bool success = instance.Predicate(fpExpression, context);

                        if (!success)
                        {
                            var text  = "Instance failed constraint " + constraintElement.ConstraintDescription();
                            var issue = constraintElement.Severity == ElementDefinition.ConstraintSeverity.Error ?
                                        Issue.CONTENT_ELEMENT_FAILS_ERROR_CONSTRAINT : Issue.CONTENT_ELEMENT_FAILS_WARNING_CONSTRAINT;

                            Trace(outcome, text, issue, instance);
                        }
                    }
                    catch (Exception e)
                    {
                        Trace(outcome, $"Evaluation of FhirPath for constraint '{constraintElement.Key}' failed: {e.Message}",
                              Issue.PROFILE_ELEMENTDEF_INVALID_FHIRPATH_EXPRESSION, instance);
                    }
                }
                else
                {
                    Trace(outcome, $"Encountered an invariant ({constraintElement.Key}) that has no FhirPath expression, skipping validation of this constraint",
                          Issue.UNSUPPORTED_CONSTRAINT_WITHOUT_FHIRPATH, instance);
                }
            }

            return(outcome);
        }
Beispiel #2
0
        /// <summary>
        /// Perform the Invariant based validation for this rule
        /// </summary>
        /// <param name="invariantRule"></param>
        /// <param name="model"></param>
        /// <param name="result">The OperationOutcome that will have the validation results appended</param>
        /// <returns></returns>
        protected static bool ValidateInvariantRule(ElementDefinition.ConstraintComponent invariantRule, IElementNavigator model, OperationOutcome result)
        {
            string expression = invariantRule.GetStringExtension("http://hl7.org/fhir/StructureDefinition/structuredefinition-expression");

            try
            {
                // No FhirPath extension
                if (string.IsNullOrEmpty(expression))
                {
                    result.Issue.Add(new OperationOutcome.IssueComponent()
                    {
                        Code        = OperationOutcome.IssueType.Invariant,
                        Severity    = OperationOutcome.IssueSeverity.Warning,
                        Details     = new CodeableConcept(null, invariantRule.Key, "Unable to validate without a FhirPath expression"),
                        Diagnostics = expression
                    });
                    return(true);
                }

                // Ensure the FHIR extensions are registered
                Hl7.Fhir.FhirPath.PocoNavigatorExtensions.PrepareFhirSybolTableFunctions();

                if (model.Predicate(expression, model))
                {
                    return(true);
                }

                result.Issue.Add(new OperationOutcome.IssueComponent()
                {
                    Code        = OperationOutcome.IssueType.Invariant,
                    Severity    = OperationOutcome.IssueSeverity.Error,
                    Details     = new CodeableConcept(null, invariantRule.Key, invariantRule.Human),
                    Diagnostics = expression
                });
                return(false);
            }
            catch (Exception ex)
            {
                result.Issue.Add(new OperationOutcome.IssueComponent()
                {
                    Code        = OperationOutcome.IssueType.Invariant,
                    Severity    = OperationOutcome.IssueSeverity.Fatal,
                    Details     = new CodeableConcept(null, invariantRule.Key, "FATAL: Unable to process the invariant rule: " + invariantRule.Key + " " + expression),
                    Diagnostics = String.Format("FhirPath: {0}\r\nError: {1}", expression, ex.Message)
                });
                return(false);
            }
        }
Beispiel #3
0
 public static bool Predicate(this IElementNavigator input, string expression, IElementNavigator resource)
 {
     return(input.Predicate(expression, new EvaluationContext(resource)));
 }