public static ElementDefinition.TypeRefComponent GetTypeRef(this ElementDefinition elementDefinition, String type, bool createFlag = false) { if (elementDefinition is null) { throw new ArgumentNullException(nameof(elementDefinition)); } foreach (ElementDefinition.TypeRefComponent typeRef in elementDefinition.Type) { if (typeRef.Code == type) { return(typeRef); } } if (createFlag == false) { return(null); } { ElementDefinition.TypeRefComponent typeRef = new ElementDefinition.TypeRefComponent { Code = type }; elementDefinition.AddType(typeRef); return(typeRef); } }
/// <summary> /// Add type. /// </summary> public static ElementDefinition AddType(this ElementDefinition elementDefinition, ElementDefinition.TypeRefComponent value) { if (elementDefinition is null) { throw new ArgumentNullException(nameof(elementDefinition)); } elementDefinition.Type.Add(value); return(elementDefinition); }
public static ElementDefinition Type(this ElementDefinition e, String code, String[] profiles = null, String[] targetProfiles = null) { ElementDefinition.TypeRefComponent t = new ElementDefinition.TypeRefComponent { Code = code, Profile = profiles, TargetProfile = targetProfiles }; return(e.Type(new ElementDefinition.TypeRefComponent[] { t })); }
/// <summary>Returns the explicit primary type profile, if specified, or otherwise the core profile url for the specified type code.</summary> public static string TypeProfile(this ElementDefinition.TypeRefComponent elemType) { string profile = null; if (elemType != null) { profile = elemType.Profile.FirstOrDefault(); if (profile == null && elemType.Code.HasValue) { profile = ModelInfo.CanonicalUriForFhirCoreType(elemType.Code.Value); } } return(profile); }
public static string GetDeclaredProfiles(this ElementDefinition.TypeRefComponent typeRef) { if (typeRef.Profile.Any()) { return(typeRef.Profile.First()); // Take the first, this will disappear in STU3 anyway } else if (typeRef.Code.HasValue) { return(ModelInfo.CanonicalUriForFhirCoreType(typeRef.Code.Value)); } else { return(null); } }
public static ElementDefinition Types(this ElementDefinition e, params String[] codes) { List <ElementDefinition.TypeRefComponent> types = new List <ElementDefinition.TypeRefComponent>(); foreach (String code in codes) { ElementDefinition.TypeRefComponent t = new ElementDefinition.TypeRefComponent { Code = code }; types.Add(t); } return(e.Type(types.ToArray())); }
public static string GetPrimitiveValueRegEx(this ElementDefinition.TypeRefComponent typeRef) { var regex = typeRef.GetStringExtension("http://hl7.org/fhir/StructureDefinition/structuredefinition-regex"); if (regex == null) { return(null); } if (regex.StartsWith("urn:oid:")) { regex = regex.Substring(8); } return(regex); }
void MergeTargetProfiles(ElementDefinition.TypeRefComponent baseTypeRef, ElementDefinition.TypeRefComponent typeRef, ref bool success) { //const String fcn = "MergeTargetProfiles"; List <String> baseTargets = baseTypeRef.TargetProfile.ToList(); foreach (string targetProfile in typeRef.TargetProfile) { if (baseTargets.Contains(targetProfile) == false) { baseTargets.Add(targetProfile); } } baseTypeRef.TargetProfile = baseTargets; }
private static double CompareTypes(ElementDefinition.TypeRefComponent type1, ElementDefinition.TypeRefComponent type2) { double factor = 0; // Different Code -> max distance if (type1.Code != type2.Code) { return(AspectWeights.WEIGHT_TYPE_CODE); } if (type1.Profile.FirstOrDefault() != type2.Profile.FirstOrDefault()) { factor += AspectWeights.WEIGHT_TYPE_PROFILE; } if (AggregationSortKey(type1.Aggregation) != AggregationSortKey(type2.Aggregation)) { factor += AspectWeights.WEIGHT_TYPE_AGGREGATION; } return(1.0 * factor); }
public static ElementDefinition OrType(this ElementDefinition ed, FHIRDefinedType type, string profile = null, IEnumerable <ElementDefinition.AggregationMode> aggs = null) { var newType = new ElementDefinition.TypeRefComponent { Code = type }; if (profile != null) { newType.Profile = new[] { profile } } ; if (aggs != null) { newType.Aggregation = aggs.Cast <ElementDefinition.AggregationMode?>(); } ed.Type.Add(newType); return(ed); }
public static String[] References(ElementTreeNode entryNode) { List <ElementDefinition.TypeRefComponent> types = entryNode.ElementDefinition.Type; if (types.Count != 1) { throw new Exception($"SingleReference. Invalid type count. Epected 1, got {types.Count}."); } ElementDefinition.TypeRefComponent type = types[0]; if (type.Code != "Reference") { throw new Exception($"SingleReference. Invalid type code. Expected 'Reference', got {type.Code}."); } List <String> retVal = new List <string>(); foreach (String targetProfile in type.TargetProfile) { retVal.Add(targetProfile); } return(retVal.ToArray()); }
void DefineClassFields( CodeBlockNested subClassBlock, CodeBlockNested fieldsBlock, CodeBlockNested constructorBlock, CodeBlockNested writeBlock, ElementDefinition[] elements, String basePath, String className, ref Int32 index) { while (index < elements.Length) { ElementDefinition ed = elements[index]; // We know when we are at the end of a sub class, when the // path does no longer start with subPath. String path = ed.Path; if (ed.Path.StartsWith(basePath) == false) { return; } path = path.Substring(basePath.Length); String elementName = ElementName(ed.Path.LastPathPart()); fieldsBlock .AppendComment($"{index}. {elements[index].Path}") .AppendCode($"public ElementDefinitionInfo {elementName};") ; writeBlock .AppendCode($"{elementName}.Write(sDef);") ; Int32 min = 0; Int32 max = -1; if (ed.Min.HasValue) { min = ed.Min.Value; } if ((String.IsNullOrEmpty(ed.Max) == false) && (ed.Max != "*")) { max = Int32.Parse(ed.Max); } constructorBlock .OpenBrace() .AppendComment($"{index}. {elements[index].Path}") .AppendCode($"this.{elementName} = new ElementDefinitionInfo") .OpenBrace() .AppendCode($"Name = \"{elementName}\",") .AppendCode($"Path= \"{ed.Path}\",") .AppendCode($"Id = \"{ed.ElementId}\",") .AppendCode($"Min = {min},") .AppendCode($"Max = {max},") .AppendCode($"Types = new BaseType[]") .OpenBrace() .DefineBlock(out CodeBlockNested typesBlock) .CloseBrace("") .CloseBrace(";") .CloseBrace("") ; // If next elements starts with this items path, then this is a // subelement, so start creating sub class. if ( (index < elements.Length - 1) && (elements[index + 1].Path.StartsWith($"{ed.Path}.")) ) { String subClassName = TypeName(path.LastPathPart()); typesBlock .AppendCode($"new {subClassName}") .OpenBrace() .CloseBrace() ; DefineClass(subClassBlock, elements, ref index, ed.Path, subClassName, ComplexBase, out CodeBlockNested dummy); } else { for (Int32 typeIndex = 0; typeIndex < ed.Type.Count; typeIndex += 1) { String sep = typeIndex == (ed.Type.Count - 1) ? "" : ","; ElementDefinition.TypeRefComponent type = ed.Type[typeIndex]; switch (type.Code) { case null: break; case "boolean": case "integer": case "decimal": case "uri": case "string": case "base64Binary": case "instant": case "date": case "dateTime": case "time": case "oid": case "id": case "markdown": case "unsignedInt": case "positiveInt": case "xhtml": case "code": case "uuid": case "url": case "canonical": { String sep1 = ""; typesBlock .AppendCode($"new {PrimitiveNameSpace}.{PrimitiveName(type.Code)}") .OpenBrace() .AppendProfiles(type.Profile, ref sep1) .AppendTargetProfiles(type.TargetProfile, ref sep1) .CloseBrace(sep) ; } sep = ", "; break; case "CodeableConcept": case "Coding": { String sep1 = ""; typesBlock .AppendCode($"new {ComplexNameSpace}.{TypeName(type.Code)}") .OpenBrace() .AppendProfiles(type.Profile, ref sep1) .AppendTargetProfiles(type.TargetProfile, ref sep1) .CloseBrace(sep) ; } sep = ", "; break; case "Resource": { String sep1 = ""; typesBlock .AppendCode($"new {ResourceNameSpace}.{ResourceName(type.Code)}") .OpenBrace() .AppendProfiles(type.Profile, ref sep1) .AppendTargetProfiles(type.TargetProfile, ref sep1) .CloseBrace(sep) ; } sep = ", "; break; case "Reference": { String sep1 = ""; typesBlock .AppendCode($"new {ComplexNameSpace}.{TypeName(type.Code)}") .OpenBrace() .AppendProfiles(type.Profile, ref sep1) .AppendTargetProfiles(type.TargetProfile, ref sep1) .CloseBrace(sep) ; } sep = ", "; break; default: typesBlock .AppendCode($"new {ComplexNameSpace}.{TypeName(type.Code)}") .OpenBrace() .CloseBrace(sep) ; sep = ", "; break; } } index += 1; } } }
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); }
/// <summary>Determines if the specified type reference represents a <see cref="ResourceReference"/>.</summary> /// <param name="typeRef">A <see cref="ElementDefinition.TypeRefComponent"/> instance.</param> /// <returns><c>true</c> if the instance defines a reference, or <c>false</c> otherwise.</returns> public static bool IsReference(this ElementDefinition.TypeRefComponent typeRef) { return(typeRef.Code.HasValue && ModelInfo.IsReference(typeRef.Code.Value)); }
static bool isExtensionSlice(ElementDefinition.TypeRefComponent type) => type != null && type.Code == FHIRDefinedType.Extension && type.Profile != null;
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); }
private static Func <OperationOutcome> createValidatorForTypeRef(Validator validator, ScopedNode instance, ElementDefinition.TypeRefComponent tr) { // In STU3, we need to do BOTH // First, call Validate() against the profile (which is then a profile on Reference) THEN validate the referenced resource if (tr.Code == FHIRDefinedType.Reference) { return(() => validator.ValidateResourceReference(instance, tr)); } else { return(() => validator.Validate(instance, tr.GetDeclaredProfiles(), statedCanonicals: null, statedProfiles: null)); } }