internal static BundleWrapper ReadEmbeddedSearchParameters( string embeddedResourceName, IModelInfoProvider modelInfoProvider, string embeddedResourceNamespace = null, Assembly assembly = null) { using Stream stream = modelInfoProvider.OpenVersionedFileStream(embeddedResourceName, embeddedResourceNamespace, assembly); using TextReader reader = new StreamReader(stream); using JsonReader jsonReader = new JsonTextReader(reader); try { ISourceNode sourceNode = FhirJsonNode.Read(jsonReader); return(new BundleWrapper(modelInfoProvider.ToTypedElement(sourceNode))); } catch (FormatException ex) { var issue = new OperationOutcomeIssue( OperationOutcomeConstants.IssueSeverity.Fatal, OperationOutcomeConstants.IssueType.Invalid, ex.Message); throw new InvalidDefinitionException( Core.Resources.SearchParameterDefinitionContainsInvalidEntry, new OperationOutcomeIssue[] { issue }); } }
public void Start() { // The json file is a bundle compiled from the compartment definitions currently defined by HL7. // The definitions are available at https://www.hl7.org/fhir/compartmentdefinition.html. using Stream stream = _modelInfoProvider.OpenVersionedFileStream("compartment.json"); using TextReader reader = new StreamReader(stream); using JsonReader jsonReader = new JsonTextReader(reader); var bundle = new BundleWrapper(FhirJsonNode.Read(jsonReader).ToTypedElement(_modelInfoProvider.StructureDefinitionSummaryProvider)); Build(bundle); }
public Task <OperationDefinitionResponse> Handle(OperationDefinitionRequest request, CancellationToken cancellationToken) { using Stream stream = DataLoader.OpenOperationDefinitionFileStream($"{request.OperationName}.json"); using TextReader reader = new StreamReader(stream); using JsonReader jsonReader = new JsonTextReader(reader); ISourceNode result = FhirJsonNode.Read(jsonReader); ITypedElement operationDefinition = result.ToTypedElement(_modelInfoProvider.StructureDefinitionSummaryProvider); return(Task.FromResult(new OperationDefinitionResponse(operationDefinition.ToResourceElement()))); }
public ITypedElement ToTypedElement(RawResource rawResource) { EnsureArg.IsNotNull(rawResource, nameof(rawResource)); using TextReader reader = new StringReader(rawResource.Data); using JsonReader jsonReader = new JsonTextReader(reader); try { ISourceNode sourceNode = FhirJsonNode.Read(jsonReader); return(sourceNode.ToTypedElement(StructureDefinitionSummaryProvider)); } catch (FormatException ex) { var issue = new OperationOutcomeIssue( OperationOutcomeConstants.IssueSeverity.Fatal, OperationOutcomeConstants.IssueType.Invalid, ex.Message); throw new ResourceNotValidException(new List <OperationOutcomeIssue>() { issue }); } }
public static MockModelInfoProviderBuilder Create(FhirSpecification version) { IModelInfoProvider provider = Substitute.For <IModelInfoProvider>(); provider.Version.Returns(version); // Adds normative types by default var seenTypes = new HashSet <string> { "Binary", "Bundle", "CapabilityStatement", "CodeSystem", "Observation", "OperationOutcome", "Patient", "StructureDefinition", "ValueSet", }; provider.GetResourceTypeNames().Returns(_ => seenTypes.Where(x => !string.IsNullOrEmpty(x)).ToArray()); provider.IsKnownResource(Arg.Any <string>()).Returns(x => provider.GetResourceTypeNames().Contains(x[0])); // Simulate inherited behavior // Some code depends on "InheritedResource".BaseType // This adds the ability to resolve "Resource" as the base type provider.GetTypeForFhirType(Arg.Any <string>()).Returns(p => p.ArgAt <string>(0) == "Resource" ? typeof(ResourceObj) : typeof(InheritedResourceObj)); provider.GetFhirTypeNameForType(Arg.Any <Type>()).Returns(p => p.ArgAt <Type>(0) == typeof(ResourceObj) ? "Resource" : null); // IStructureDefinitionSummaryProvider allows the execution of FHIRPath queries provider.ToTypedElement(Arg.Any <ISourceNode>()) .Returns(p => p.ArgAt <ISourceNode>(0).ToTypedElement(new MockStructureDefinitionSummaryProvider(p.ArgAt <ISourceNode>(0), seenTypes))); provider.ToTypedElement(Arg.Any <RawResource>()) .Returns(r => { using TextReader reader = new StringReader(r.ArgAt <RawResource>(0).Data); using JsonReader jsonReader = new JsonTextReader(reader); ISourceNode sourceNode = FhirJsonNode.Read(jsonReader); return(sourceNode.ToTypedElement(new MockStructureDefinitionSummaryProvider(sourceNode, seenTypes))); }); return(new MockModelInfoProviderBuilder(provider, seenTypes)); }
/// <summary> /// Converts the RawResource to an ITypedElement /// </summary> /// <param name="rawResource">The RawResource to convert</param> /// <param name="modelInfoProvider">The IModelInfoProvider to use when converting the RawResource</param> /// <returns>An ITypedElement of the RawResource</returns> public static ITypedElement ToITypedElement(this RawResource rawResource, IModelInfoProvider modelInfoProvider) { EnsureArg.IsNotNull(rawResource, nameof(rawResource)); EnsureArg.IsNotNull(modelInfoProvider, nameof(modelInfoProvider)); using TextReader reader = new StringReader(rawResource.Data); using JsonReader jsonReader = new JsonTextReader(reader); try { ISourceNode sourceNode = FhirJsonNode.Read(jsonReader); return(modelInfoProvider.ToTypedElement(sourceNode)); } catch (FormatException ex) { var issue = new OperationOutcomeIssue( OperationOutcomeConstants.IssueSeverity.Fatal, OperationOutcomeConstants.IssueType.Invalid, ex.Message); throw new InvalidDefinitionException( Core.Resources.SearchParameterDefinitionContainsInvalidEntry, new OperationOutcomeIssue[] { issue }); } }
private List <(string ResourceType, SearchParameterInfo SearchParameter)> ValidateAndGetFlattenedList() { var issues = new List <OperationOutcomeIssue>(); BundleWrapper bundle = null; using (Stream stream = _modelInfoProvider.OpenVersionedFileStream(_embeddedResourceName, _embeddedResourceNamespace, _assembly)) { using TextReader reader = new StreamReader(stream); using JsonReader jsonReader = new JsonTextReader(reader); try { bundle = new BundleWrapper(FhirJsonNode.Read(jsonReader).ToTypedElement(_modelInfoProvider.StructureDefinitionSummaryProvider)); } catch (FormatException ex) { AddIssue(ex.Message); } } EnsureNoIssues(); IReadOnlyList <BundleEntryWrapper> entries = bundle.Entries; // Do the first pass to make sure all resources are SearchParameter. for (int entryIndex = 0; entryIndex < entries.Count; entryIndex++) { // Make sure resources are not null and they are SearchParameter. BundleEntryWrapper entry = entries[entryIndex]; ITypedElement searchParameterElement = entry.Resource; if (searchParameterElement == null || !string.Equals(searchParameterElement.InstanceType, KnownResourceTypes.SearchParameter, StringComparison.OrdinalIgnoreCase)) { AddIssue(Core.Resources.SearchParameterDefinitionInvalidResource, entryIndex); continue; } var searchParameter = new SearchParameterWrapper(searchParameterElement); try { SearchParameterInfo searchParameterInfo = CreateSearchParameterInfo(searchParameter); _uriDictionary.Add(new Uri(searchParameter.Url), searchParameterInfo); } catch (FormatException) { AddIssue(Core.Resources.SearchParameterDefinitionInvalidDefinitionUri, entryIndex); continue; } catch (ArgumentException) { AddIssue(Core.Resources.SearchParameterDefinitionDuplicatedEntry, searchParameter.Url); continue; } } EnsureNoIssues(); var validatedSearchParameters = new List <(string ResourceType, SearchParameterInfo SearchParameter)> { // _type is currently missing from the search params definition bundle, so we inject it in here. (KnownResourceTypes.Resource, new SearchParameterInfo(SearchParameterNames.ResourceType, SearchParamType.Token, SearchParameterNames.ResourceTypeUri, null, "Resource.type().name", null)), }; // Do the second pass to make sure the definition is valid. for (int entryIndex = 0; entryIndex < entries.Count; entryIndex++) { BundleEntryWrapper entry = entries[entryIndex]; ITypedElement searchParameterElement = entry.Resource; var searchParameter = new SearchParameterWrapper(searchParameterElement); // If this is a composite search parameter, then make sure components are defined. if (string.Equals(searchParameter.Type, SearchParamType.Composite.GetLiteral(), StringComparison.OrdinalIgnoreCase)) { var composites = searchParameter.Component; if (composites.Count == 0) { AddIssue(Core.Resources.SearchParameterDefinitionInvalidComponent, searchParameter.Url); continue; } for (int componentIndex = 0; componentIndex < composites.Count; componentIndex++) { ITypedElement component = composites[componentIndex]; var definitionUrl = GetComponentDefinition(component); if (definitionUrl == null || !_uriDictionary.TryGetValue(new Uri(definitionUrl), out SearchParameterInfo componentSearchParameter)) { AddIssue( Core.Resources.SearchParameterDefinitionInvalidComponentReference, searchParameter.Url, componentIndex); continue; } if (componentSearchParameter.Type == SearchParamType.Composite) { AddIssue( Core.Resources.SearchParameterDefinitionComponentReferenceCannotBeComposite, searchParameter.Url, componentIndex); continue; } if (string.IsNullOrWhiteSpace(component.Scalar("expression")?.ToString())) { AddIssue( Core.Resources.SearchParameterDefinitionInvalidComponentExpression, searchParameter.Url, componentIndex); continue; } } } // Make sure the base is defined. var bases = searchParameter.Base; if (bases.Count == 0) { AddIssue(Core.Resources.SearchParameterDefinitionBaseNotDefined, searchParameter.Url); continue; } for (int baseElementIndex = 0; baseElementIndex < bases.Count; baseElementIndex++) { var code = bases[baseElementIndex]; string baseResourceType = code; // Make sure the expression is not empty unless they are known to have empty expression. // These are special search parameters that searches across all properties and needs to be handled specially. if (ShouldExcludeEntry(baseResourceType, searchParameter.Name) || (_modelInfoProvider.Version == FhirSpecification.R5 && _knownBrokenR5.Contains(new Uri(searchParameter.Url)))) { continue; } else { if (string.IsNullOrWhiteSpace(searchParameter.Expression)) { AddIssue(Core.Resources.SearchParameterDefinitionInvalidExpression, searchParameter.Url); continue; } } validatedSearchParameters.Add((baseResourceType, CreateSearchParameterInfo(searchParameter))); } } EnsureNoIssues(); return(validatedSearchParameters); void AddIssue(string format, params object[] args) { issues.Add(new OperationOutcomeIssue( OperationOutcomeConstants.IssueSeverity.Fatal, OperationOutcomeConstants.IssueType.Invalid, string.Format(CultureInfo.InvariantCulture, format, args))); } void EnsureNoIssues() { if (issues.Count != 0) { throw new InvalidDefinitionException( Core.Resources.SearchParameterDefinitionContainsInvalidEntry, issues.ToArray()); } } }