예제 #1
0
        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);
            }
        }
예제 #2
0
 /// <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);
 }
예제 #3
0
 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);
        }
예제 #5
0
 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);
     }
 }
예제 #6
0
        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()));
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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());
        }
예제 #12
0
파일: MakerGen.cs 프로젝트: Gjoll/FhirKhit
        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));
 }
예제 #15
0
 static bool isExtensionSlice(ElementDefinition.TypeRefComponent type)
 => type != null &&
 type.Code == FHIRDefinedType.Extension &&
 type.Profile != null;
예제 #16
0
        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);
        }
예제 #17
0
 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));
     }
 }