public static IEnumerable <Scope> Harvest(IElementNavigator instance) { var scanner = instance.Clone(); if (ModelInfo.FhirTypeNameToFhirType(scanner.Type) == FHIRDefinedType.Bundle) { return(HarvestBundle(scanner)); } else if (ModelInfo.IsKnownResource(instance.Type)) { return(HarvestResource(instance)); } else { return(Enumerable.Empty <Scope>()); } }
/// <summary>Harvest specific summary information from a <see cref="StructureDefinition"/> resource.</summary> /// <returns><c>true</c> if the current target represents a <see cref="StructureDefinition"/> resource, or <c>false</c> otherwise.</returns> /// <remarks>The <see cref="ArtifactSummaryGenerator"/> calls this method from a <see cref="ArtifactSummaryHarvester"/> delegate.</remarks> public static bool Harvest(IElementNavigator nav, ArtifactSummaryPropertyBag properties) { if (IsStructureDefinitionSummary(properties)) { // Explicit extractor chaining if (ConformanceSummaryProperties.Harvest(nav, properties)) { nav.HarvestValue(properties, FhirVersionKey, "fhirVersion"); nav.HarvestValue(properties, KindKey, "kind"); nav.HarvestValue(properties, ConstrainedTypeKey, "constrainedType"); nav.HarvestValue(properties, ContextTypeKey, "contextType"); nav.HarvestValue(properties, BaseKey, "base"); } return(true); } return(false); }
private static T getValue <T>(this IElementNavigator val, string name) { if (val == null) { throw Error.ArgumentNull(name); } if (val.Value == null) { throw Error.ArgumentNull(name + ".Value"); } if (!(val.Value is T)) { throw Error.Argument(name + " must be of type " + typeof(T).Name); } return((T)val.Value); }
private static bool compare(XElement expected, IElementNavigator actual) { var type = expected.Attribute("type").Value; var tp = (IElementNavigator)actual; Assert.True(type == tp.Type, "incorrect output type"); if (expected.IsEmpty) { return(true); // we are not checking the value } var value = expected.Value; Assert.True(value.Equals(actual.ToStringRepresentation()), "incorrect output value"); return(true); }
public virtual OperationOutcome Validate(Validator validator, IElementNavigator errorLocation) { var outcome = new OperationOutcome(); if (!Cardinality.InRange(Members.Count)) { OperationOutcome.IssueComponent issue = validator.Trace(outcome, $"Instance count for '{Name}' is {Members.Count}, which is not within the specified cardinality of {Cardinality.ToString()}", Issue.CONTENT_INCORRECT_OCCURRENCE, errorLocation); if (issue != null) { // the location in the structure definition (this will match to the discriminator when checking slicing) // issue.LocationElement.Add(new FhirString(Path)); issue.SetAnnotation(new SlicePathAnnotation(Path)); } } return(outcome); }
internal static FHIRDefinedType?DetermineType(ElementDefinition definition, IElementNavigator instance) { if (definition.IsChoice()) { if (instance.Type != null) { return(ModelInfo.FhirTypeNameToFhirType(instance.Type)); } else { return(null); } } else { return(definition.Type.First().Code.Value); } }
public static Closure Root(IElementNavigator root, EvaluationContext ctx = null) { var newContext = new Closure() { EvaluationContext = ctx ?? EvaluationContext.Default }; var input = new[] { root }; newContext.SetThis(input); newContext.SetThat(input); newContext.SetOriginalContext(input); if (ctx.Container != null) { newContext.SetResource(new[] { ctx.Container }); } return(newContext); }
internal OperationOutcome ValidateBinding(ElementDefinition definition, IElementNavigator instance) { var outcome = new OperationOutcome(); if (definition.Binding == null) { return(outcome); } var ts = Settings.TerminologyService; if (ts == null) { if (Settings.ResourceResolver == null) { Trace(outcome, $"Cannot resolve binding references since neither TerminologyService nor ResourceResolver is given in the settings", Issue.UNAVAILABLE_TERMINOLOGY_SERVER, instance); return(outcome); } ts = new LocalTerminologyService(Settings.ResourceResolver); } var bindingValidator = new BindingValidator(ts, instance.Location); try { Element bindable = instance.ParseBindable(); // If the instance is not bindeable, ignore the Binding specified on the element, // it's simply not applicable if (bindable != null) { return(bindingValidator.ValidateBinding(bindable, definition.Binding)); } } catch (Exception e) { Trace(outcome, $"Terminology service call failed for binding at {definition.Path}: {e.Message}", Issue.TERMINOLOGY_SERVICE_FAILED, instance); } return(outcome); }
public override bool Add(IElementNavigator candidate) { var report = Validator.Validate(candidate, Root); // If the instance matches everything in the slice, it's definitely a member if (report.Success) { Members.Add(candidate); _successes.Add(report); return(true); } // Now, it did not validate against the constraints... if (Discriminator?.Any() == true) { // Get the full path of the discriminator, which is rooted in the current instance path var baseInstancePath = candidate.Location; // remove all the [num] (from the instance path) and [x] (from the discriminator path) in one go, // so a path looking like this remains as a discriminator: Patient.deceased // (note won't work if deceasedBoolean is allowed as a discriminator vlaue) var discriminatorPaths = Discriminator.Select(d => strip(baseInstancePath + "." + d)).ToArray(); if (errorOnDiscriminator(discriminatorPaths, report)) { // Failed on a discriminator => this instance does not belong to this slice return(false); } else { // Validated against the discriminating elements, instance belongs to this slice although there // are validation errors on other elements Members.Add(candidate); _failures.Add(report); return(true); } } else { // No discriminator, and validation failed => not a member of this slice return(false); } }
public static IEnumerable <IElementNavigator> Navigate(this IElementNavigator element, string name) { if (!(element is IElementNavigator)) { return(FhirValueList.Empty); } var nav = (IElementNavigator)element; if (char.IsUpper(name[0])) { if (!char.IsUpper(nav.Name[0])) { throw Error.InvalidOperation("Resource type name may only appear at the root of a document"); } // If we are at a resource, we should match a path that is possibly not rooted in the resource // (e.g. doing "name.family" on a Patient is equivalent to "Patient.name.family") if (nav is IElementNavigator) { if (((IElementNavigator)nav).TypeName == name) { return(new List <IElementNavigator>() { nav }); } else { return(Enumerable.Empty <IElementNavigator>()); } } else { throw Error.InvalidOperation("Cannot verify whether the root object is of type '{0}'. ".FormatWith(name) + "You could try leaving out the resource name of the expression."); } } else { return(nav.GetChildrenByName(name)); } }
public static MatchResult Match(ElementDefinitionNavigator definitionParent, IElementNavigator instanceParent) { List <ElementDefinitionNavigator> definitionElements = harvestDefinitionNames(definitionParent); List <IElementNavigator> elementsToMatch = instanceParent.Children().ToList(); List <Match> matches = new List <Match>(); foreach (var definitionElement in definitionElements) { var match = new Match() { Definition = definitionElement, InstanceElements = new List <IElementNavigator>() }; // Special case is the .value of a primitive fhir type, this is represented // as the "Value" of the IValueProvider interface, not as a real child if (definitionElement.Current.IsPrimitiveValueConstraint()) { if (instanceParent.Value != null) { match.InstanceElements.Add(instanceParent); } } else { var definitionPath = ProfileNavigationExtensions.GetNameFromPath(definitionElement.Current?.Base?.Path ?? definitionElement.Path); var found = elementsToMatch.Where(ie => NameMatches(definitionPath, ie)).ToList(); match.InstanceElements.AddRange(found); elementsToMatch.RemoveAll(e => found.Contains(e)); } matches.Add(match); } MatchResult result = new MatchResult(); result.Matches = matches; result.UnmatchedInstanceElements = elementsToMatch; return(result); }
public ProfilePreprocessor(Func <string, StructureDefinition> profileResolver, Action <StructureDefinition> snapshotGenerator, IElementNavigator instance, string declaredTypeProfile, IEnumerable <StructureDefinition> additionalProfiles, IEnumerable <string> additionalCanonicals) { _profileResolver = profileResolver; _snapshotGenerator = snapshotGenerator; _path = instance.Location; _profiles = new ProfileAssertion(_path, _profileResolver); if (instance.Type != null) { _profiles.SetInstanceType(ModelInfo.CanonicalUriForFhirCoreType(instance.Type)); } if (declaredTypeProfile != null) { _profiles.SetDeclaredType(declaredTypeProfile); } // This is only for resources, but I don't bother checking, since this will return empty anyway _profiles.AddStatedProfile(instance.Children("meta").Children("profile").Select(p => p.Value).Cast <string>()); //Almost identically, extensions can declare adherance to a profile using the 'url' attribute if (declaredTypeProfile == ModelInfo.CanonicalUriForFhirCoreType(FHIRDefinedType.Extension)) { var urlDeclaration = instance.Children("url").FirstOrDefault()?.Value as string; if (urlDeclaration != null && urlDeclaration.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) { _profiles.AddStatedProfile(urlDeclaration); } } if (additionalProfiles != null) { _profiles.AddStatedProfile(additionalProfiles); } if (additionalCanonicals != null) { _profiles.AddStatedProfile(additionalCanonicals); } }
public IList <ResIndexUriType> Set(IElementNavigator oElement, DtoServiceSearchParameterLight SearchParameter) { var UriIndexList = IUriSetter.Set(oElement, SearchParameter); if (UriIndexList.Count == 0) { return(null); } var DbReferenceIndexList = new List <ResIndexUriType>(); foreach (IUriIndex Index in UriIndexList) { var DbResourceIndex = new ResIndexUriType(); DbResourceIndex.Uri = Index.Uri; DbResourceIndex.ServiceSearchParameterId = Index.ServiceSearchParameterLight.Id; DbReferenceIndexList.Add(DbResourceIndex); } return(DbReferenceIndexList); }
private OperationOutcome ValidateExtension(IExtendable elementDef, IElementNavigator instance, string uri) { var outcome = new OperationOutcome(); var pattern = elementDef.GetStringExtension(uri); if (pattern != null) { var regex = new Regex(pattern); var value = toStringRepresentation(instance); var success = Regex.Match(value, "^" + regex + "$").Success; if (!success) { Trace(outcome, $"Value '{value}' does not match regex '{regex}'", Issue.CONTENT_ELEMENT_INVALID_PRIMITIVE_VALUE, instance); } } return(outcome); }
/// <summary> /// Parses a bindeable type into either a Coding (code, Coding, Quantity, string, uri) or CodeableConcept /// </summary> /// <param name="instance"></param> /// <param name="codedType"></param> /// <returns>An object, which is either a Coding or CodeableConcept</returns> public static object ParseBindable(this IElementNavigator instance, FHIRDefinedType codedType) { // 'code','Coding','CodeableConcept','Quantity','Extension', 'string', 'uri' if (codedType == FHIRDefinedType.Code) { return(instance.ParsePrimitiveCode()); } else if (codedType == FHIRDefinedType.Coding) { return(instance.ParseCoding()); } else if (codedType == FHIRDefinedType.CodeableConcept) { return(instance.ParseCodeableConcept()); } else if (codedType == FHIRDefinedType.Quantity) { var newCoding = new Coding(); var q = instance.ParseQuantity(); newCoding.Code = q.Unit; newCoding.System = q.System; return(newCoding); } else if (codedType == FHIRDefinedType.String) { return(instance.ParsePrimitiveCode()); } else if (codedType == FHIRDefinedType.Uri) { return(instance.ParsePrimitiveCode()); } else if (codedType == FHIRDefinedType.Extension) { throw new NotSupportedException($"The validator does not support binding to Extension values"); } else { throw new NotSupportedException($"FHIR type '{codedType}' is not bindeable"); } }
public PatientFixture() { var parser = new Hl7.Fhir.Serialization.FhirXmlParser(); var tpXml = TestData.ReadTextFile("fp-test-patient.xml"); var patient = parser.Parse <Patient>(tpXml); TestInput = new PocoNavigator(patient); tpXml = TestData.ReadTextFile("questionnaire-example.xml"); var quest = parser.Parse <Questionnaire>(tpXml); Questionnaire = new PocoNavigator(quest); tpXml = TestData.ReadTextFile("uuid.profile.xml"); var uuid = parser.Parse <StructureDefinition>(tpXml); UuidProfile = new PocoNavigator(uuid); Xdoc = new XDocument(new XElement("group", new XAttribute("name", "CSharpTests"))); }
private static bool namesAreEqual(IElementNavigator left, IElementNavigator right, bool useEquivalence = false) { // If the values have names, compare them if (left.IsNamedNode() && right.IsNamedNode()) // -- if (left is INamedNode && right is INamedNode) { //-- var lNP = (INamedNode)left; //-- var rNP = (INamedNode)right; if (useEquivalence && left.Name == "id") { return(true); // don't compare 'id' elements for equivalence } if (left.Name != right.Name) { return(false); } } return(true); }
public static string ToString(IElementNavigator nav) { var result = ""; if (nav.IsNamedNode()) { result = nav.Name; } if (nav.IsTypeProvider()) { result += ": " + nav.TypeName; } if (nav.Value != null) { result += " = " + nav.Value; } return(result); }
/// <summary>Harvest an array of child element values into a property bag.</summary> /// <param name="nav">An <see cref="IElementNavigator"/> instance.</param> /// <param name="properties">A property bag to store harvested summary information.</param> /// <param name="key">A property key.</param> /// <param name="element">An element name.</param> /// <param name="childElement">A child element name.</param> public static bool HarvestValues(this IElementNavigator nav, IDictionary <string, object> properties, string key, string element, string childElement) { if (nav.Find(element)) { var values = new List <string>(); do { var childNav = nav.Clone(); if (childNav.MoveToFirstChild(childElement)) { HarvestValue(childNav, values); } } while (nav.MoveToNext(element)); if (values.Count > 0) { properties[key] = values.ToArray(); return(true); } } return(false); }
/// <summary>Harvest extension values into a property bag.</summary> /// <param name="nav">An <see cref="IElementNavigator"/> instance.</param> /// <param name="properties">A property bag to store harvested summary information.</param> /// <param name="extensionValueHarvester">Callback function called for each individual extension entry.</param> public static void HarvestExtensions(this IElementNavigator nav, IDictionary <string, object> properties, Action <IElementNavigator, IDictionary <string, object>, string> extensionValueHarvester) { const string extension = "extension"; if (nav.Find(extension)) { do { var childNav = nav.Clone(); if (childNav.MoveToFirstChild("url")) { if (childNav.Value is string url) { extensionValueHarvester(childNav, properties, url); } } // [WMR 20171219] BUG: MoveToNext advances to extension.url (child attribute) instead of the next extension element } while (nav.MoveToNext(extension)); } }
public IList <ResIndexTokenType> Set(IElementNavigator oElement, DtoServiceSearchParameterLight SearchParameter) { var TokenIndexList = ITokenSetter.Set(oElement, SearchParameter); if (TokenIndexList.Count == 0) { return(null); } var DbReferenceIndexList = new List <ResIndexTokenType>(); foreach (ITokenIndex Index in TokenIndexList) { var DbResourceIndex = new ResIndexTokenType(); DbResourceIndex.Code = Index.Code; DbResourceIndex.System = Index.System; DbResourceIndex.ServiceSearchParameterId = Index.ServiceSearchParameterLight.Id; DbReferenceIndexList.Add(DbResourceIndex); } return(DbReferenceIndexList); }
/// <summary>Harvest specific summary information from a <see cref="ConceptMap"/> resource.</summary> /// <returns><c>true</c> if the current target represents a <see cref="ConceptMap"/> resource, or <c>false</c> otherwise.</returns> /// <remarks>The <see cref="ArtifactSummaryGenerator"/> calls this method from a <see cref="ArtifactSummaryHarvester"/> delegate.</remarks> public static bool Harvest(IElementNavigator nav, ArtifactSummaryPropertyBag properties) { if (IsConceptMapSummary(properties)) { // Explicit extractor chaining if (ConformanceSummaryProperties.Harvest(nav, properties)) { if (!nav.HarvestValue(properties, SourceKey, "sourceUri")) { nav.HarvestValue(properties, SourceKey, "sourceReference", "reference"); } if (!nav.HarvestValue(properties, TargetKey, "targetUri")) { nav.HarvestValue(properties, TargetKey, "targetReference", "reference"); } } return(true); } return(false); }
public IList <ResIndexUriType> Set(IElementNavigator oElement, DtoServiceSearchParameterLight SearchParameter) { var ResourceIndexList = new List <ResIndexUriType>(); var ServiceSearchParameterId = SearchParameter.Id; if (oElement is Hl7.Fhir.ElementModel.PocoNavigator Poco && Poco.FhirValue != null) { if (Poco.FhirValue is FhirUri FhirUri) { SetUri(FhirUri, ResourceIndexList); } else if (Poco.FhirValue is Oid Oid) { SetOid(Oid, ResourceIndexList); } else { throw new FormatException($"Unknown FhirType: '{oElement.Type}' for SearchParameterType: '{SearchParameter.Type}'"); } ResourceIndexList.ForEach(x => x.ServiceSearchParameterId = ServiceSearchParameterId); return(ResourceIndexList); }
public static Model.Quantity ParseQuantity(this IElementNavigator instance) { var newQuantity = new Quantity(); newQuantity.Value = instance.Children("value").SingleOrDefault()?.Value as decimal?; var comp = instance.Children("comparator").GetString(); if (comp != null) { newQuantity.ComparatorElement = new Code <Quantity.QuantityComparator> { ObjectValue = comp } } ; newQuantity.Unit = instance.Children("unit").GetString(); newQuantity.System = instance.Children("system").GetString(); newQuantity.Code = instance.Children("code").GetString(); return(newQuantity); }
public Base Parse(IElementNavigator nav, Type dataType) { if (nav == null) { throw Error.ArgumentNull(nameof(nav)); } if (dataType == null) { throw Error.ArgumentNull(nameof(dataType)); } var reader = new ElementNavFhirReader(nav, Settings.DisallowXsiAttributesOnRoot); if (dataType.CanBeTreatedAsType(typeof(Resource))) { return(new ResourceReader(reader, Settings).Deserialize()); } else { return(new ComplexTypeReader(reader, Settings).Deserialize(dataType)); } }
public IList <IDateTimeIndex> Set(IElementNavigator oElement, DtoServiceSearchParameterLight SearchParameter) { var ResourceIndexList = new List <IDateTimeIndex>(); _SearchParameter = SearchParameter; if (oElement is Hl7.Fhir.ElementModel.PocoNavigator Poco && Poco.FhirValue != null) { if (Poco.FhirValue is Date Date) { SetDate(Date, ResourceIndexList); } else if (Poco.FhirValue is Period Period) { SetPeriod(Period, ResourceIndexList); } else if (Poco.FhirValue is FhirDateTime FhirDateTime) { SetDateTime(FhirDateTime, ResourceIndexList); } else if (Poco.FhirValue is FhirString FhirString) { SetString(FhirString, ResourceIndexList); } else if (Poco.FhirValue is Instant Instant) { SetInstant(Instant, ResourceIndexList); } else if (Poco.FhirValue is Timing Timing) { SetTiming(Timing, ResourceIndexList); } else { throw new FormatException($"Unknown FhirType: '{oElement.Type}' for SearchParameterType: '{SearchParameter.Type}'"); } return(ResourceIndexList); }
private static IElementNavigator ResolveReference(this Validator validator, IElementNavigator instance, string reference, out ElementDefinition.AggregationMode?referenceKind, OperationOutcome outcome) { var identity = new ResourceIdentity(reference); if (identity.Form == ResourceIdentityForm.Undetermined) { if (!Uri.IsWellFormedUriString(reference, UriKind.RelativeOrAbsolute)) { validator.Trace(outcome, $"Encountered an unparseable reference ({reference})", Issue.CONTENT_UNPARSEABLE_REFERENCE, instance); referenceKind = null; return(null); } } var result = validator.ScopeTracker.Resolve(instance, reference); if (identity.Form == ResourceIdentityForm.Local) { referenceKind = ElementDefinition.AggregationMode.Contained; if (result == null) { validator.Trace(outcome, $"Contained reference ({reference}) is not resolvable", Issue.CONTENT_CONTAINED_REFERENCE_NOT_RESOLVABLE, instance); } } else { if (result != null) { referenceKind = ElementDefinition.AggregationMode.Bundled; } else { referenceKind = ElementDefinition.AggregationMode.Referenced; } } return(result); }
private string toStringRepresentation(IElementNavigator vp) { if (vp == null || vp.Value == null) { return(null); } var val = vp.Value; if (val is string) { return((string)val); } else if (val is long) { return(XmlConvert.ToString((long)val)); } else if (val is decimal) { return(XmlConvert.ToString((decimal)val)); } else if (val is bool) { return((bool)val ? "true" : "false"); } else if (val is Model.Primitives.PartialTime) { return(((Model.Primitives.PartialTime)val).ToString()); } else if (val is Model.Primitives.PartialDateTime) { return(((Model.Primitives.PartialDateTime)val).ToString()); } else { return(val.ToString()); } }
public IList <IStringIndex> Set(IElementNavigator oElement, DtoServiceSearchParameterLight SearchParameter) { _SearchParameter = SearchParameter; var ResourceIndexList = new List <IStringIndex>(); var ServiceSearchParameterId = SearchParameter.Id; if (oElement is Hl7.Fhir.ElementModel.PocoNavigator Poco && Poco.FhirValue != null) { if (Poco.FhirValue is FhirString FhirString) { SetFhirString(FhirString, ResourceIndexList); } else if (Poco.FhirValue is Address address) { SetAddress(address, ResourceIndexList); } else if (Poco.FhirValue is HumanName HumanName) { SetHumanName(HumanName, ResourceIndexList); } else if (Poco.FhirValue is Markdown Markdown) { SetMarkdown(Markdown, ResourceIndexList); } else if (Poco.FhirValue is Annotation Annotation) { SetAnnotation(Annotation, ResourceIndexList); } else if (Poco.FhirValue is Base64Binary Base64Binary) { //No good purpose to index base64 content as a search index } else { throw new FormatException($"Unknown FhirType: '{oElement.Type}' for SearchParameterType: '{SearchParameter.Type}'"); } }
public static bool Matches(this IElementNavigator value, IElementNavigator pattern) { if (value == null && pattern == null) { return(true); } if (value == null || pattern == null) { return(false); } if (!ValueEquality(value.Value, pattern.Value)) { return(false); } // Compare the children. var valueChildren = value.Children(); var patternChildren = pattern.Children(); return(patternChildren.All(patternChild => valueChildren.Any(valueChild => patternChild.Name == valueChild.Name && valueChild.Matches(patternChild)))); }