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); }
public void TestPatientWithOrganization() { // DirectorySource (and ResourceStreamScanner) does not support json... // var source = new DirectorySource(@"TestData\validation"); // var res = source.ResolveByUri("Patient/pat1"); // cf. "Patient/Levin" var jsonPatient = File.ReadAllText(@"TestData\validation\patient-ck.json"); var parser = new FhirJsonParser(); var patient = parser.Parse <Patient>(jsonPatient); Assert.IsNotNull(patient); var jsonOrganization = File.ReadAllText(@"TestData\validation\organization-ck.json"); var organization = parser.Parse <Organization>(jsonOrganization); Assert.IsNotNull(organization); var resources = new Resource[] { patient, organization }; var memResolver = new InMemoryResourceResolver(resources); // [WMR 20161220] Validator always uses existing snapshots if present // ProfilePreprocessor.GenerateSnapshots: // if (!sd.HasSnapshot) { ... snapshotGenerator(sd) ... } // Create custom source to properly force snapshot expansion // Run validator on instance // Afterwards, verify that instance profile has been expanded var source = new CachedResolver( // Clear snapshots after initial load // This will force the validator to regenerate all snapshots new ClearSnapshotResolver( new MultiResolver( // new BundleExampleResolver(@"TestData\validation"), // new DirectorySource(@"TestData\validation"), // new TestProfileArtifactSource(), memResolver, new ZipSource("specification.zip")))); var ctx = new ValidationSettings() { ResourceResolver = source, GenerateSnapshot = true, EnableXsdValidation = true, Trace = false, ResolveExteralReferences = true }; var validator = new Validator(ctx); var report = validator.Validate(patient); Assert.IsTrue(report.Success); // Assert.AreEqual(4, report.Warnings); // To check for ele-1 constraints on expanded Patient snapshot: // source.FindStructureDefinitionForCoreType(FHIRDefinedType.Patient).Snapshot.Element.Select(e=>e.Path + " : " + e.Constraint.FirstOrDefault()?.Key ?? "").ToArray() var patientStructDef = source.FindStructureDefinitionForCoreType(FHIRDefinedType.Patient); Assert.IsNotNull(patientStructDef); Assert.IsTrue(patientStructDef.HasSnapshot); assertElementConstraints(patientStructDef.Snapshot.Element); }
public static OperationOutcome Validate(this Validator me, Base instance, params string[] definitionUri) { return(me.Validate(new PocoNavigator(instance), definitionUri)); }
public static OperationOutcome Validate(this Validator me, Base instance, IEnumerable <StructureDefinition> structureDefinitions) { return(me.Validate(new PocoNavigator(instance), structureDefinitions)); }
public static OperationOutcome Validate(this Validator me, Base instance) { return(me.Validate(new PocoNavigator(instance))); }
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); }
public static OperationOutcome Validate(this Validator me, Base instance, IEnumerable <StructureDefinition> structureDefinitions) { return(me.Validate(instance.ToTypedElement(), structureDefinitions)); }
public static OperationOutcome Validate(this Validator me, Base instance, params string[] definitionUri) { return(me.Validate(instance.ToTypedElement(), definitionUri)); }
public static OperationOutcome Validate(this Validator me, Base instance) { return(me.Validate(instance.ToTypedElement())); }