コード例 #1
0
        internal static OperationOutcome ValidateResourceReference(this Validator validator, ScopedNode instance, ElementDefinition.TypeRefComponent typeRef)
        {
            var outcome = new OperationOutcome();

            var reference = instance.ParseResourceReference()?.Reference;

            if (reference == null)       // No reference found -> this is always valid
            {
                return(outcome);
            }


            // Try to resolve the reference *within* the current instance (Bundle, resource with contained resources) first
            var referencedResource = validator.resolveReference(instance, reference,
                                                                out ElementDefinition.AggregationMode? encounteredKind, outcome);

            // Validate the kind of aggregation.
            // If no aggregation is given, all kinds of aggregation are allowed, otherwise only allow
            // those aggregation types that are given in the Aggregation element
            bool hasAggregation = typeRef.Aggregation != null && typeRef.Aggregation.Count() != 0;

            if (hasAggregation && !typeRef.Aggregation.Any(a => a == encounteredKind))
            {
                validator.Trace(outcome, $"Encountered a reference ({reference}) of kind '{encounteredKind}' which is not allowed", Issue.CONTENT_REFERENCE_OF_INVALID_KIND, instance);
            }

            // Bail out if we are asked to follow an *external reference* when this is disabled in the settings
            if (validator.Settings.ResolveExteralReferences == false && encounteredKind == ElementDefinition.AggregationMode.Referenced)
            {
                return(outcome);
            }

            // If we failed to find a referenced resource within the current instance, try to resolve it using an external method
            if (referencedResource == null && encounteredKind == ElementDefinition.AggregationMode.Referenced)
            {
                try
                {
                    referencedResource = validator.ExternalReferenceResolutionNeeded(reference, outcome, instance.Location);
                }
                catch (Exception e)
                {
                    validator.Trace(outcome, $"Resolution of external reference {reference} failed. Message: {e.Message}",
                                    Issue.UNAVAILABLE_REFERENCED_RESOURCE, instance);
                }
            }

            // If the reference was resolved (either internally or externally, validate it
            if (referencedResource != null)
            {
                validator.Trace(outcome, $"Starting validation of referenced resource {reference} ({encounteredKind})", Issue.PROCESSING_START_NESTED_VALIDATION, instance);

                // References within the instance are dealt with within the same validator,
                // references to external entities will operate within a new instance of a validator (and hence a new tracking context).
                // In both cases, the outcome is included in the result.
                OperationOutcome childResult;

                if (encounteredKind != ElementDefinition.AggregationMode.Referenced)
                {
                    childResult = validator.Validate(referencedResource, typeRef.GetDeclaredProfiles(), statedProfiles: null, statedCanonicals: null);
                }
                else
                {
                    var newValidator = validator.NewInstance();
                    childResult = newValidator.Validate(referencedResource, typeRef.GetDeclaredProfiles(), statedProfiles: null, statedCanonicals: null);
                }

                // Prefix each path with the referring resource's path to keep the locations
                // interpretable
                foreach (var issue in childResult.Issue)
                {
                    issue.Location = issue.Location.Concat(new string[] { instance.Location });
                }

                outcome.Include(childResult);
            }
            else
            {
                validator.Trace(outcome, $"Cannot resolve reference {reference}", Issue.UNAVAILABLE_REFERENCED_RESOURCE, instance);
            }

            return(outcome);
        }
コード例 #2
0
        internal static OperationOutcome ValidateResourceReference(this Validator validator, IElementNavigator instance, ElementDefinition.TypeRefComponent typeRef)
        {
            var outcome = new OperationOutcome();

            var references = instance.GetChildrenByName("reference");
            var reference  = references.FirstOrDefault()?.Value as string;

            if (reference == null)       // No reference found -> this is always valid
            {
                return(outcome);
            }

            if (references.Count() > 1)
            {
                validator.Trace(outcome, $"Encountered multiple references, just using first ({reference})", Issue.CONTENT_REFERENCE_HAS_MULTIPLE_REFERENCES, instance);
            }

            // Try to resolve the reference *within* the current instance (Bundle, resource with contained resources) first
            ElementDefinition.AggregationMode?encounteredKind;
            var referencedResource = validator.ResolveReference(instance, reference, out encounteredKind, outcome);

            // Validate the kind of aggregation.
            // If no aggregation is given, all kinds of aggregation are allowed, otherwise only allow
            // those aggregation types that are given in the Aggregation element
            bool hasAggregation = typeRef.Aggregation != null && typeRef.Aggregation.Count() != 0;

            if (hasAggregation && !typeRef.Aggregation.Any(a => a == encounteredKind))
            {
                validator.Trace(outcome, $"Encountered a reference ({reference}) of kind '{encounteredKind}' which is not allowed", Issue.CONTENT_REFERENCE_OF_INVALID_KIND, instance);
            }

            // If we failed to find a referenced resource within the current instance, try to resolve it using an external method
            if (referencedResource == null && encounteredKind == ElementDefinition.AggregationMode.Referenced)
            {
                try
                {
                    referencedResource = validator.ExternalReferenceResolutionNeeded(reference, outcome, instance);
                }
                catch (Exception e)
                {
                    validator.Trace(outcome, $"Resolution of external reference {reference} failed. Message: {e.Message}",
                                    Issue.UNAVAILABLE_REFERENCED_RESOURCE, instance);
                }
            }

            // If the reference was resolved (either internally or externally, validate it
            if (referencedResource != null)
            {
                validator.Trace(outcome, $"Starting validation of referenced resource {reference} ({encounteredKind})", Issue.PROCESSING_START_NESTED_VALIDATION, instance);

                // References within the instance are dealt with within the same validator,
                // references to external entities will operate within a new instance of a validator (and hence a new tracking context).
                // In both cases, the outcome is included in the result.
                if (encounteredKind != ElementDefinition.AggregationMode.Referenced)
                {
                    outcome.Include(validator.Validate(referencedResource, typeRef.GetDeclaredProfiles(), statedProfiles: null, statedCanonicals: null));
                }
                else
                {
                    var newValidator = validator.NewInstance();
                    outcome.Include(newValidator.Validate(referencedResource, typeRef.GetDeclaredProfiles(), statedProfiles: null, statedCanonicals: null));
                }
            }
            else
            {
                validator.Trace(outcome, $"Cannot resolve reference {reference}", Issue.UNAVAILABLE_REFERENCED_RESOURCE, instance);
            }

            return(outcome);
        }