public void TestSourceCaching() { var src = new CachedResolver(new MultiResolver(ZipSource.CreateValidationSource(), new WebResolver())); Stopwatch sw1 = new Stopwatch(); // Ensure looking up a failed endpoint repeatedly does not cost much time sw1.Start(); src.ResolveByUri("http://some.none.existant.address.nl/fhir/StructureDefinition/bla"); sw1.Stop(); var sw2 = new Stopwatch(); sw2.Start(); src.ResolveByUri("http://some.none.existant.address.nl/fhir/StructureDefinition/bla"); sw2.Stop(); Debug.WriteLine("sw2 {0}, sw1 {1}", sw2.ElapsedMilliseconds, sw1.ElapsedMilliseconds); Assert.IsTrue(sw2.ElapsedMilliseconds <= sw1.ElapsedMilliseconds && sw2.ElapsedMilliseconds < 100); // Now try an existing artifact sw1.Restart(); src.ResolveByUri("http://hl7.org/fhir/ValueSet/v2-0292"); sw1.Stop(); sw2.Restart(); src.ResolveByUri("http://hl7.org/fhir/ValueSet/v2-0292"); sw2.Stop(); Assert.IsTrue(sw2.ElapsedMilliseconds < sw1.ElapsedMilliseconds && sw2.ElapsedMilliseconds < 100); }
public void SetupSource() { // Ensure the FHIR extensions are registered Hl7.Fhir.FhirPath.PocoNavigatorExtensions.PrepareFhirSymbolTableFunctions(); // Prepare the artifact resolvers (cache to reduce complexity) _source = new CachedResolver( new MultiResolver( // Use the specification zip that is local (from the NuGet package) new ZipSource("specification.zip"), // Try using the fixed content new AustralianFhirProfileResolver(), // Then look to a specific FHIR Registry Server new WebResolver(id => new FhirClient("http://sqlonfhir-stu3.azurewebsites.net/fhir")) ) ); var ctx = new ValidationSettings() { ResourceResolver = _source, GenerateSnapshot = true, EnableXsdValidation = true, Trace = false, ResolveExteralReferences = true }; // until we have a local terminology service ready, here is the remote implementation // ctx.TerminologyService = new ExternalTerminologyService(new FhirClient("http://test.fhir.org/r3")); ctx.TerminologyService = new LocalTerminologyServer(_source); _validator = new Validator(ctx); }
protected TypeDefinition GetTypeDef <T> () { var type = typeof(T); var path = type.Module.Assembly.Location; var assemblyResolver = new MDocResolver(); var projPath = typeof(CecilBaseTest).Module.Assembly.Location; var dependencyPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(projPath), "..", "..", "..", "..", "external", "Windows"); assemblyResolver.AddSearchDirectory(dependencyPath); var cachedResolver = new CachedResolver(assemblyResolver); if (!System.IO.Directory.Exists(dependencyPath)) { throw new System.Exception($"The path '{dependencyPath}' doesn't seem to exist ... did project files get moved around?"); } var resolver = new MDocMetadataResolver(cachedResolver); var assembly = AssemblyDefinition.ReadAssembly(path, new ReaderParameters { AssemblyResolver = cachedResolver, MetadataResolver = resolver }); var typeref = assembly.MainModule.GetAllTypes().FirstOrDefault(t => t.Name == type.Name); return(typeref); }
static void InitUserProfiles() { Console.WriteLine($"Fetch profiles in target location..."); var src = _dirSource = new DirectorySource(_targetPath, includeSubDirs); _cachedDirSource = new CachedResolver(src); var userProfiles = _userProfiles = src.ListResourceUris().ToList(); Console.WriteLine($"Found {userProfiles.Count} profiles."); Console.WriteLine($"Determine mappings..."); foreach (var profile in userProfiles) { var sd = _cachedDirSource.FindStructureDefinition(profile, false); if (EnsureSnapshot(sd)) { var key = ModelInfo.CanonicalUriForFhirCoreType(sd.Type); if (!_mappings.TryGetValue(key, out string existing)) { Console.WriteLine($"Map references of type '{sd.Type}' to user profile '{sd.Url}'"); _mappings.Add(key, sd.Url); } else { Console.WriteLine($"Warning! Ignore duplicate user profile '{sd.Url}' for reference target type '{sd.Type}'"); } } } }
public void Setup() { var assembly = Assembly.GetExecutingAssembly(); var location = new Uri(assembly.GetName().CodeBase); var directoryInfo = new FileInfo(location.AbsolutePath).Directory; Debug.Assert(directoryInfo != null, "directoryInfo != null"); Debug.Assert(directoryInfo.FullName != null, "directoryInfo.FullName != null"); var structureDefinitions = directoryInfo.FullName + @"\Resources\StructureDefinitions"; var includeSubDirectories = new DirectorySourceSettings { IncludeSubDirectories = true }; var directorySource = new DirectorySource(structureDefinitions, includeSubDirectories); var cachedResolver = new CachedResolver(directorySource); var coreSource = new CachedResolver(ZipSource.CreateValidationSource()); var combinedSource = new MultiResolver(cachedResolver, coreSource); var settings = new ValidationSettings { EnableXsdValidation = true, GenerateSnapshot = true, Trace = true, ResourceResolver = combinedSource, ResolveExteralReferences = true, SkipConstraintValidation = false }; var validator = new Validator(settings); _profileValidator = new ProfileValidator(validator); }
public void FullRoundtripOfAllExamplesJsonNavSdProvider() { var source = new CachedResolver(ZipSource.CreateValidationSource()); FullRoundtripOfAllExamples("examples-json.zip", "FHIRRoundTripTestJson", "Roundtripping json->xml->json", usingPoco: false, provider: new StructureDefinitionSummaryProvider(source)); }
int validate() { int returncode = 0; // Example from https://stackoverflow.com/questions/53399139/fhir-net-api-stu3-validating // https://www.devdays.com/wp-content/uploads/2019/02/DD18-US-Validation-in-NET-and-Java-Ewout-Kramer-James-Agnew-2018-06-19.pdf // https://blog.fire.ly/2016/10/27/validation-and-other-new-features-in-the-net-api-stack/ // setup the resolver to use specification.zip, and a folder with custom profiles var source = new CachedResolver(new MultiResolver( new DirectorySource(@"C:\Users\dag\source\repos\FhirTool\SfmFhir\Profiles\"), ZipSource.CreateValidationSource())); // prepare the settings for the validator var ctx = new ValidationSettings() { ResourceResolver = source, GenerateSnapshot = true, Trace = false, EnableXsdValidation = true, ResolveExternalReferences = false }; var validator = new Validator(ctx); // validate the resource; optionally enter a custom profile url as 2nd parameter var result = validator.Validate(this); return(returncode); }
public void CannotCreateNestedSnapshotSource() { var orgSource = ZipSource.CreateValidationSource(); var cachedSource = new CachedResolver(orgSource); var src = new SnapshotSource(cachedSource); // Verify that SnapshotSource ctor rejects SnapshotSource arguments Assert.ThrowsException <ArgumentException>(() => new SnapshotSource(src)); }
protected override IResourceResolver GetResourceResolver() { var includeSubDirectories = new DirectorySourceSettings { IncludeSubDirectories = true }; var directorySource = new DirectorySource(_structureDefinitionsFolder, includeSubDirectories); var cachedResolver = new CachedResolver(directorySource); return(cachedResolver); }
static void InitCoreProfiles() { Console.WriteLine("Load FHIR core resource definitions..."); var src = _coreSource = ZipSource.CreateValidationSource(); _cachedCoreSource = new CachedResolver(src); var profiles = _coreProfiles = src.ListResourceUris(ResourceType.StructureDefinition).ToList(); Console.WriteLine($"Found {profiles.Count} core definitions."); }
public async void RunSnapshotMultiThreaded() { // Arrange var source = new CachedResolver(new ZipSource("specification.zip")); var generator = new SnapshotGenerator(source); OperationOutcome GenerateSnapshot(StructureDefinition sd) { generator.Update(sd); System.Diagnostics.Debug.WriteLine(sd.HasSnapshot); return(generator.Outcome ?? new OperationOutcome()); } var nrOfParrallelTasks = 100; var results = new ConcurrentBag <OperationOutcome>(); var buffer = new BufferBlock <StructureDefinition>(); var processor = new ActionBlock <StructureDefinition>(sd => { // Act var outcome = ProfilePreprocessor.GenerateSnapshots(new[] { sd }, GenerateSnapshot, "unittest"); results.Add(outcome); } , new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 100 }); buffer.LinkTo(processor, new DataflowLinkOptions { PropagateCompletion = true }); var patientSD = source.ResolveByCanonicalUri("http://hl7.org/fhir/StructureDefinition/Patient") as StructureDefinition; // Clear snapshots after initial load // This will force the validator to regenerate all snapshots if (patientSD.HasSnapshot) { patientSD.Snapshot = null; } for (int i = 0; i < nrOfParrallelTasks; i++) { buffer.Post(patientSD); } buffer.Complete(); await processor.Completion; // Assert var nrOfSuccess = results.Count(r => r.Success); Assert.Equal(nrOfParrallelTasks, nrOfSuccess); }
public void SetupSource() { source = new CachedResolver( new MultiResolver( new TestProfileArtifactSource(), new ZipSource("specification.zip"))); var ctx = new ValidationSettings() { ResourceResolver = source, GenerateSnapshot = true, Trace = false }; validator = new Validator(ctx); }
public MainForm() { InitializeComponent(); btnErrors.Tag = "OFF"; btnWarnings.Tag = "OFF"; btnMessages.Tag = "OFF"; btnError_Click(btnErrors, null); btnWarning_Click(btnWarnings, null); btnMessage_Click(btnMessages, null); // Create a resource resolver that searches for the core resources in 'specification.zip', which comes with the .NET FHIR Specification NuGet package // We create a source that takes its contents from a ZIP file (in this case the default 'specification.zip'). We decorate that source by encapsulating // it in a CachedResolver, which speeds up access by caching conformance resources once we got them from the large files in the ZIP. CoreSource = new CachedResolver(ZipSource.CreateValidationSource()); }
public async Task TestCacheOnSyncAsync() { var sync = new SyncResolver(new AResource { Data = 1 }); var c1 = new CachedResolver(sync); await test(c1); Assert.AreEqual(1, sync.ByUri); Assert.AreEqual(1, sync.ByCanonical); var async = new AsyncResolver(new AResource { Data = 1 }); var c2 = new CachedResolver(async); await test(c2); Assert.AreEqual(1, async.ByUriAsync); Assert.AreEqual(1, async.ByCanonicalAsync); var sasync = new SyncAsyncResolver(new AResource { Data = 1 }); var c3 = new CachedResolver(sasync); await test(c3); Assert.AreEqual(0, sasync.ByUri); // cache will always prefer the async Assert.AreEqual(0, sasync.ByCanonical); // cache will always prefer the async Assert.AreEqual(1, sasync.ByUriAsync); Assert.AreEqual(1, sasync.ByCanonicalAsync); async Task test(CachedResolver r) { #pragma warning disable CS0618 // Type or member is obsolete var result = r.ResolveByUri("t") as AResource; #pragma warning restore CS0618 // Type or member is obsolete Assert.AreEqual(1, result.Data); result = await r.ResolveByCanonicalUriAsync("t") as AResource; Assert.AreEqual(1, result.Data); } }
public ScanResources(string existingSDpath, string newSDpath, string outputProfileBaseUri, string publisher) { _publisher = publisher; _outputProfileBaseUri = outputProfileBaseUri; _outputProfilePath = newSDpath; ds = new DirectorySource(_outputProfilePath, new DirectorySourceSettings() { IncludeSubDirectories = true }); sourceSD = new CachedResolver( new MultiResolver( ds, new DirectorySource(existingSDpath, new DirectorySourceSettings() { IncludeSubDirectories = true }), new ZipSource(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "specification.zip")) ) ); }
public void SetupSource() { _source = new CachedResolver( new MultiResolver( new BundleExampleResolver(@"TestData\validation"), new DirectorySource(@"TestData\validation"), new TestProfileArtifactSource(), new ZipSource("specification.zip"))); var ctx = new ValidationSettings() { ResourceResolver = _source, GenerateSnapshot = true, EnableXsdValidation = true, Trace = false, ResolveExteralReferences = true }; _validator = new Validator(ctx); }
public void TestCacheInvalidation() { var src = new CachedResolver(new MultiResolver(ZipSource.CreateValidationSource())); CachedResolver.LoadResourceEventArgs eventArgs = null; CachedResolver.LoadResourceEventHandler handler = (sender, args) => { eventArgs = args; }; src.Load += handler; // Verify that the Load event is fired on the initial load const string resourceUri = "http://hl7.org/fhir/ValueSet/v2-0292"; var resource = src.ResolveByUri(resourceUri); Assert.IsNotNull(eventArgs); Assert.AreEqual(resourceUri, eventArgs.Url); Assert.AreEqual(resource, eventArgs.Resource); // Verify that the Load event is not fired on subsequent load eventArgs = null; resource = src.ResolveByUri(resourceUri); Assert.IsNull(eventArgs); // Verify that we can remove the cache entry var result = src.InvalidateByUri(resourceUri); Assert.IsTrue(result); // Verify that the cache entry has been removed result = src.InvalidateByUri(resourceUri); Assert.IsFalse(result); // Verify that the Load event is fired again on the next load var resource2 = src.ResolveByUri(resourceUri); Assert.IsNotNull(eventArgs); Assert.AreEqual(resourceUri, eventArgs.Url); Assert.AreEqual(resource2, eventArgs.Resource); // Verify that the cache returned a new instance with exact same value Assert.AreNotEqual(resource2.GetHashCode(), resource.GetHashCode()); Assert.IsTrue(resource.IsExactly(resource2)); }
public ValidationFixture() { Resolver = new CachedResolver( new MultiResolver( new BasicValidationTests.BundleExampleResolver(Path.Combine("TestData", "validation")), new DirectorySource(Path.Combine("TestData", "validation")), new TestProfileArtifactSource(), new ZipSource("specification.zip"))); var ctx = new ValidationSettings() { ResourceResolver = Resolver, GenerateSnapshot = true, EnableXsdValidation = true, Trace = false, ResolveExteralReferences = true }; Validator = new Validator(ctx); }
public Validator GetValidator() { if (!IsValidationOn()) { return(null); } var zipSource = ZipSource.CreateValidationSource(); var coreSource = new CachedResolver(zipSource); var combinedSource = new MultiResolver(GetResourceResolver(), coreSource); var settings = new ValidationSettings { EnableXsdValidation = true, GenerateSnapshot = true, Trace = true, ResourceResolver = combinedSource, ResolveExteralReferences = true, SkipConstraintValidation = false }; return(new Validator(settings)); }
public ValidationFixture() { var zip = ZipSource.CreateValidationSource(); Resolver = new CachedResolver( new MultiResolver( new TestProfileArtifactSource(), new DirectorySource(@"TestData\validation"), zip )); var ctx = new ValidationSettings() { ResourceResolver = Resolver, GenerateSnapshot = true, EnableXsdValidation = true, Trace = false, ResolveExteralReferences = true }; Validator = new Validator(ctx); }
public ProfileValidator(bool validateXsd, bool showTrace, bool reloadValidator, string profileFolder) { if (_validator != null && !reloadValidator) { return; } var coreSource = new CachedResolver(ZipSource.CreateValidationSource()); var cachedResolver = new CachedResolver(new DirectorySource(profileFolder, new DirectorySourceSettings { IncludeSubDirectories = true })); var combinedSource = new MultiResolver(cachedResolver, coreSource); var settings = new ValidationSettings { EnableXsdValidation = validateXsd, GenerateSnapshot = true, Trace = showTrace, ResourceResolver = combinedSource, ResolveExteralReferences = true, SkipConstraintValidation = false }; _validator = new Validator(settings); }
public void SetupSource() { // Ensure the FHIR extensions are registered Hl7.Fhir.FhirPath.PocoNavigatorExtensions.PrepareFhirSymbolTableFunctions(); _source = new CachedResolver( new MultiResolver( new BundleExampleResolver(@"TestData\validation"), new DirectorySource(@"TestData\validation"), new TestProfileArtifactSource(), new ZipSource("specification.zip"))); var ctx = new ValidationSettings() { ResourceResolver = _source, GenerateSnapshot = true, EnableXsdValidation = true, Trace = false, ResolveExteralReferences = true }; _validator = new Validator(ctx); }
public static Validator GetValidator() { var structureDefinitions = GetStructureDefinitionsPath(); var includeSubDirectories = new DirectorySourceSettings { IncludeSubDirectories = true }; var directorySource = new DirectorySource(structureDefinitions, includeSubDirectories); var cachedResolver = new CachedResolver(directorySource); var coreSource = new CachedResolver(ZipSource.CreateValidationSource()); var combinedSource = new MultiResolver(cachedResolver, coreSource); var settings = new ValidationSettings { EnableXsdValidation = true, GenerateSnapshot = true, Trace = true, ResourceResolver = combinedSource, ResolveExternalReferences = true, SkipConstraintValidation = false }; var validator = new Validator(settings); return(validator); }
public void TestCacheLoadingStrategy() { const string resourceUri = "http://hl7.org/fhir/ValueSet/v2-0292"; // Create empty in-memory resolver var mem = new InMemoryProfileResolver(); var cache = new CachedResolver(mem); // Load on demand should return null var resource = cache.ResolveByCanonicalUri(resourceUri); Assert.IsNull(resource); // Resolve core resource from ZIP and refresh in-memory resolver var zipSource = ZipSource.CreateValidationSource(); var original = zipSource.ResolveByUri(resourceUri) as ValueSet; Assert.IsNotNull(original); mem.Reload(original); // Load on demand should still return null resource = cache.ResolveByCanonicalUri(resourceUri); Assert.IsNull(resource); // Invalidate the cache, delete existing cache entry cache.InvalidateByCanonicalUri(resourceUri); // Load from cache should still return null resource = cache.ResolveByCanonicalUri(resourceUri, CachedResolverLoadingStrategy.LoadFromCache); Assert.IsNull(resource); // Load on demand should now resolve instance and update cache resource = cache.ResolveByCanonicalUri(resourceUri); Assert.IsNotNull(resource); Assert.AreEqual(original, resource); Assert.IsTrue(cache.IsCachedCanonicalUri(resourceUri)); // Update in-memory resolver with new, modified instance (same url) var modified = (ValueSet)original.DeepCopy(); modified.Name = "MODIFIED"; mem.Reload(modified); // Load on demand should still return the original, unmodified instance from cache // As the cache is unaware that the internal source has changed resource = cache.ResolveByCanonicalUri(resourceUri); Assert.IsNotNull(resource); Assert.AreEqual(original, resource); // Forced load should update cache and return new, modified instance resource = cache.ResolveByCanonicalUri(resourceUri, CachedResolverLoadingStrategy.LoadFromSource); Assert.IsNotNull(resource); Assert.AreEqual(modified, resource); // Clear in-memory resolver; i.e. simulate delete file from disk mem.Clear(); // Load on demand should still return the modified instance from cache // As the cache is unaware that the internal source has changed resource = cache.ResolveByCanonicalUri(resourceUri); Assert.IsNotNull(resource); Assert.AreEqual(modified, resource); Assert.IsTrue(cache.IsCachedCanonicalUri(resourceUri)); // Forced load should update cache and now return null resource = cache.ResolveByCanonicalUri(resourceUri, CachedResolverLoadingStrategy.LoadFromSource); Assert.IsNull(resource); Assert.IsFalse(cache.IsCachedCanonicalUri(resourceUri)); }
public void TestElementSnapshot() { // Request core Element snapshot; verify recursion handling var orgSource = ZipSource.CreateValidationSource(); var cachedSource = new CachedResolver(orgSource); // Assumption: source provides Element structure var sdCached = cachedSource.FindStructureDefinitionForCoreType(FHIRDefinedType.Element); Assert.IsNotNull(sdCached); Assert.IsNotNull(sdCached.Differential); var elemCnt = sdCached.Differential.Element.Count; Assert.AreEqual(3, elemCnt); // Element | Element.id | Element.extension // Generate snapshot by calling SnapshotSource // Important! Specify flag to force re-generation (don't trust existing core snapshots...) var snapSource = new SnapshotSource(cachedSource, true); var sd = snapSource.FindStructureDefinitionForCoreType(FHIRDefinedType.Element); Assert.IsNotNull(sd); Assert.AreEqual(sdCached, sd); // Expecting same (cached) object reference, with updated Snapshot component Assert.IsTrue(sd.HasSnapshot); Assert.IsTrue(sd.Snapshot.IsCreatedBySnapshotGenerator()); var elems = sd.Snapshot.Element; Assert.AreEqual(elemCnt, elems.Count); void assert_ele1(ElementDefinition eld) { Assert.AreEqual("ele-1", eld.Constraint.FirstOrDefault()?.Key); Assert.AreEqual("ele-1", eld.Condition.FirstOrDefault()); } // Assumption: differential introduces constraint "ele-1" on root element (only) var diffElems = sd.Differential.Element; assert_ele1(diffElems[0]); for (int i = 1; i < elemCnt; i++) { var elem = diffElems[i]; Assert.IsFalse(elem.Constraint.Any()); Assert.IsFalse(elem.Condition.Any()); } // Verify explicit inheritance of recursive constraints in snapshot // // [0] Element // [1] Element.id : id < string < Element // [2] Element.extension : Extension < Element // // Verify that the "ele-1" constraint & condition, introduced by diff root element [0], // is correctly propagated to snapshot child elements [1] and [2] foreach (var elem in elems) { assert_ele1(elem); } }
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); }
protected override IResourceResolver GetResourceResolver() { var cachedResolver = new CachedResolver(new DirectorySource(_structureDefinitionsFolder, true)); return(cachedResolver); }