Пример #1
0
        /// <summary>
        /// Gets the @id value of the element/constraint.
        /// </summary>
        /// <param name="constraint"></param>
        /// <returns></returns>
        /// <remarks>Creates the value based on the context of the constraint and each parent, and based on whether the parents are a branch</remarks>
        public static string GetElementId(this TemplateConstraint constraint)
        {
            string             elementId = string.Empty;
            TemplateConstraint current   = constraint;
            bool checkBranch             = true;

            while (current != null)
            {
                string separator = current.IsChoice ? ":" : ".";

                if (!string.IsNullOrEmpty(elementId))
                {
                    elementId = separator + elementId;
                }

                if (checkBranch && current.IsBranch)
                {
                    elementId   = current.GetElementPath(constraint.Template.PrimaryContextType) + ":" + current.GetSliceName() + elementId;
                    checkBranch = false;
                }
                else
                {
                    elementId = current.Context + elementId;
                }

                current = current.ParentConstraint;
            }

            if (checkBranch)
            {
                return(constraint.Template.PrimaryContextType + "." + elementId);
            }

            return(elementId);
        }
Пример #2
0
        public void GetFHIRElementPathTest()
        {
            TemplateConstraint tc1 = new TemplateConstraint();

            tc1.Context = "extension";

            TemplateConstraint tc2 = new TemplateConstraint();

            tc2.Context          = "value[x]";
            tc2.IsChoice         = true;
            tc2.ParentConstraint = tc1;

            TemplateConstraint tc3 = new TemplateConstraint();

            tc3.Context          = "valueCodeableConcept";
            tc3.ParentConstraint = tc2;

            string path1 = tc1.GetElementPath("Observation");
            string path2 = tc2.GetElementPath("Observation");
            string path3 = tc3.GetElementPath("Observation");

            Assert.AreEqual("Observation.extension", path1);
            Assert.AreEqual("Observation.extension.value[x]", path2);
            Assert.AreEqual("Observation.extension.valueCodeableConcept", path3);
        }
        public void CreateElementDefinition(
            StructureDefinition strucDef,
            TemplateConstraint constraint,
            SimpleSchema.SchemaObject schemaObject)
        {
            if (constraint.IsPrimitive)     // Skip primitives (for now, at least)
            {
                return;
            }

            string sliceName           = constraint.GetSliceName();
            string elementPath         = constraint.GetElementPath(strucDef.Type != null ? strucDef.Type.ToString() : null);
            var    igSettings          = GetIGSettings(constraint);
            var    constraintFormatter = FormattedConstraintFactory.NewFormattedConstraint(this.tdb, igSettings, this.igTypePlugin, constraint);
            string definition          = constraintFormatter.GetPlainText(false, false, false);

            if (definition == null)
            {
                definition = string.Empty;
            }

            ElementDefinition newElementDef = new ElementDefinition()
            {
                Short      = !string.IsNullOrEmpty(constraint.Label) ? constraint.Label : constraint.Context,
                Label      = !string.IsNullOrEmpty(constraint.Label) ? constraint.Label : null,
                Comment    = !string.IsNullOrEmpty(constraint.Notes) ? constraint.Notes : null,
                Path       = elementPath,
                SliceName  = sliceName,
                Definition = definition,
                ElementId  = constraint.GetElementId()
            };

            if (constraint.IsChoice)
            {
                newElementDef.Slicing = new ElementDefinition.SlicingComponent();
                newElementDef.Slicing.Discriminator.Add(new ElementDefinition.DiscriminatorComponent()
                {
                    Type = ElementDefinition.DiscriminatorType.Type,
                    Path = "$this"
                });
                newElementDef.Slicing.Rules = ElementDefinition.SlicingRules.Open;
            }
            else if (constraint.Parent != null && constraint.Parent.IsChoice)
            {
                newElementDef.SliceName = constraint.Context;
            }

            // Cardinality
            if (!string.IsNullOrEmpty(constraint.Cardinality))
            {
                newElementDef.Min = constraint.CardinalityType.Left;
                newElementDef.Max = constraint.CardinalityType.Right == Cardinality.MANY ? "*" : constraint.CardinalityType.Right.ToString();
            }

            // Binding
            string valueConformance = string.IsNullOrEmpty(constraint.ValueConformance) ? constraint.Conformance : constraint.ValueConformance;
            bool   hasBinding       = constraint.References.Any(y => y.ReferenceType == ConstraintReferenceTypes.Template);

            if (constraint.ValueSet != null && valueConformance.IndexOf("NOT") < 0)
            {
                hasBinding            = true;
                newElementDef.Binding = new ElementDefinition.ElementDefinitionBindingComponent()
                {
                    ValueSet = new ResourceReference()
                    {
                        Reference = constraint.ValueSet.GetIdentifier(ValueSetIdentifierTypes.HTTP),
                        Display   = constraint.ValueSet.Name
                    }
                };

                if (valueConformance == "SHALL")
                {
                    newElementDef.Binding.Strength = BindingStrength.Required;
                }
                else if (valueConformance == "SHOULD")
                {
                    newElementDef.Binding.Strength = BindingStrength.Preferred;
                }
                else if (valueConformance == "MAY")
                {
                    newElementDef.Binding.Strength = BindingStrength.Example;
                }
            }

            // Single-Value Binding
            if (schemaObject != null && (!string.IsNullOrEmpty(constraint.Value) || !string.IsNullOrEmpty(constraint.DisplayName)))
            {
                Element elementBinding = null;

                hasBinding = true;
                switch (schemaObject.DataType)
                {
                case "CodeableConcept":
                    var codableConceptBinding = new CodeableConcept();
                    var coding = new Coding();
                    codableConceptBinding.Coding.Add(coding);

                    if (!string.IsNullOrEmpty(constraint.Value))
                    {
                        coding.Code = constraint.Value;
                    }

                    if (constraint.CodeSystem != null)
                    {
                        coding.System = constraint.CodeSystem.Oid;
                    }

                    if (!string.IsNullOrEmpty(constraint.DisplayName))
                    {
                        coding.Display = constraint.DisplayName;
                    }

                    elementBinding = codableConceptBinding;
                    break;

                case "Coding":
                    var codingBinding = new Coding();

                    if (!string.IsNullOrEmpty(constraint.Value))
                    {
                        codingBinding.Code = constraint.Value;
                    }

                    if (constraint.CodeSystem != null)
                    {
                        codingBinding.System = constraint.CodeSystem.Oid;
                    }

                    if (!string.IsNullOrEmpty(constraint.DisplayName))
                    {
                        codingBinding.Display = constraint.DisplayName;
                    }

                    elementBinding = codingBinding;
                    break;

                case "code":
                    var codeBinding = new Code();
                    codeBinding.Value = !string.IsNullOrEmpty(constraint.Value) ? constraint.Value : constraint.DisplayName;
                    elementBinding    = codeBinding;
                    break;

                default:
                    var stringBinding = new FhirString();
                    stringBinding.Value = !string.IsNullOrEmpty(constraint.Value) ? constraint.Value : constraint.DisplayName;
                    elementBinding      = stringBinding;
                    break;
                }

                if (constraint.IsFixed)
                {
                    newElementDef.Fixed = elementBinding;
                }
                else
                {
                    newElementDef.Pattern = elementBinding;
                }
            }

            // Add the type of the element when bound to a value set
            if (hasBinding && schemaObject != null && !string.IsNullOrEmpty(schemaObject.DataType))
            {
                StructureDefinition profile = GetBaseProfile(constraint.Template);
                newElementDef.Type = GetProfileDataTypes(profile, constraint);

                var containedTemplates = (from tcr in constraint.References
                                          join t in this.tdb.Templates on tcr.ReferenceIdentifier equals t.Oid
                                          where tcr.ReferenceType == ConstraintReferenceTypes.Template
                                          select new { Identifier = t.Oid, t.PrimaryContextType });

                // If there is a contained template/profile, make sure it supports a "Reference" type, and then output the profile identifier in the type
                if (containedTemplates.Count() > 0 && newElementDef.Type.Exists(y => y.Code == "Reference" || y.Code == "Extension"))
                {
                    if (!string.IsNullOrEmpty(newElementDef.SliceName))
                    {
                        var foundMatchingElement = strucDef.Differential.Element.SingleOrDefault(y => y.Path == newElementDef.Path && y.SliceName == newElementDef.SliceName);

                        if (foundMatchingElement != null)
                        {
                            foundMatchingElement.Definition += " " + definition;
                            newElementDef = foundMatchingElement;
                        }
                    }

                    var containedTypes = new List <ElementDefinition.TypeRefComponent>();
                    foreach (var containedTemplate in containedTemplates)
                    {
                        bool isExtension = containedTemplate.PrimaryContextType == "Extension" && newElementDef.Type.Exists(y => y.Code == "Extension");

                        containedTypes.Add(new ElementDefinition.TypeRefComponent()
                        {
                            Code          = isExtension ? "Extension" : "Reference",
                            Profile       = isExtension ? containedTemplate.Identifier : null,
                            TargetProfile = !isExtension ? containedTemplate.Identifier : null
                        });
                    }

                    newElementDef.Type = containedTypes;
                }
            }

            // Add the element to the list if it's new
            if (!strucDef.Differential.Element.Contains(newElementDef))
            {
                strucDef.Differential.Element.Add(newElementDef);
            }

            // Children
            foreach (var childConstraint in constraint.ChildConstraints.OrderBy(y => y.Order))
            {
                var childSchemaObject = schemaObject != null?schemaObject.Children.SingleOrDefault(y => y.Name == childConstraint.Context) : null;

                CreateElementDefinition(strucDef, childConstraint, childSchemaObject);
            }
        }
        public void CreateElementDefinition(
            StructureDefinition strucDef,
            TemplateConstraint constraint,
            SimpleSchema.SchemaObject schemaObject,
            string sliceName = null)
        {
            if (constraint.IsPrimitive)     // Skip primitives (for now, at least)
            {
                return;
            }

            string newSliceName = null;

            if (constraint.IsBranch)
            {
                newSliceName = string.Format("{0}_slice_pos{1}", constraint.Context, constraint.Order);
            }

            var igSettings          = GetIGSettings(constraint);
            var constraintFormatter = FormattedConstraintFactory.NewFormattedConstraint(this.tdb, igSettings, this.igTypePlugin, constraint);

            ElementDefinition newElementDef = new ElementDefinition()
            {
                Short      = !string.IsNullOrEmpty(constraint.Label) ? constraint.Label : constraint.Context,
                Label      = !string.IsNullOrEmpty(constraint.Label) ? constraint.Label : null,
                Comments   = !string.IsNullOrEmpty(constraint.Notes) ? constraint.Notes : null,
                Path       = constraint.GetElementPath(strucDef.ConstrainedType),
                Name       = constraint.IsBranch ? newSliceName : sliceName,
                Definition = constraintFormatter.GetPlainText(false, false, false)
            };

            // Cardinality
            if (!string.IsNullOrEmpty(constraint.Cardinality))
            {
                newElementDef.Min = constraint.CardinalityType.Left;
                newElementDef.Max = constraint.CardinalityType.Right == Cardinality.MANY ? "*" : constraint.CardinalityType.Right.ToString();
            }

            // Binding
            string valueConformance = string.IsNullOrEmpty(constraint.ValueConformance) ? constraint.Conformance : constraint.ValueConformance;
            bool   hasBinding       = constraint.References.Any(y => y.ReferenceType == ConstraintReferenceTypes.Template);

            if (constraint.ValueSet != null && valueConformance.IndexOf("NOT") < 0)
            {
                hasBinding            = true;
                newElementDef.Binding = new ElementDefinition.ElementDefinitionBindingComponent()
                {
                    ValueSet = new ResourceReference()
                    {
                        Reference = string.Format("ValueSet/{0}", constraint.ValueSet.Id),
                        Display   = constraint.ValueSet.Name
                    }
                };

                if (valueConformance == "SHALL")
                {
                    newElementDef.Binding.Strength = BindingStrength.Required;
                }
                else if (valueConformance == "SHOULD")
                {
                    newElementDef.Binding.Strength = BindingStrength.Preferred;
                }
                else if (valueConformance == "MAY")
                {
                    newElementDef.Binding.Strength = BindingStrength.Example;
                }
            }

            // Single-Value Binding
            if (schemaObject != null && (!string.IsNullOrEmpty(constraint.Value) || !string.IsNullOrEmpty(constraint.DisplayName)))
            {
                hasBinding = true;
                switch (schemaObject.DataType)
                {
                case "CodeableConcept":
                    var fixedCodeableConcept = new CodeableConcept();
                    var coding = new Coding();
                    fixedCodeableConcept.Coding.Add(coding);

                    if (!string.IsNullOrEmpty(constraint.Value))
                    {
                        coding.Code = constraint.Value;
                    }

                    if (constraint.CodeSystem != null)
                    {
                        coding.System = constraint.CodeSystem.Oid;
                    }

                    if (!string.IsNullOrEmpty(constraint.DisplayName))
                    {
                        coding.Display = constraint.DisplayName;
                    }

                    newElementDef.Fixed = fixedCodeableConcept;
                    break;

                case "Coding":
                    var fixedCoding = new Coding();

                    if (!string.IsNullOrEmpty(constraint.Value))
                    {
                        fixedCoding.Code = constraint.Value;
                    }

                    if (constraint.CodeSystem != null)
                    {
                        fixedCoding.System = constraint.CodeSystem.Oid;
                    }

                    if (!string.IsNullOrEmpty(constraint.DisplayName))
                    {
                        fixedCoding.Display = constraint.DisplayName;
                    }

                    newElementDef.Fixed = fixedCoding;
                    break;

                case "code":
                    var fixedCode = new Code();
                    fixedCode.Value     = !string.IsNullOrEmpty(constraint.Value) ? constraint.Value : constraint.DisplayName;
                    newElementDef.Fixed = fixedCode;
                    break;

                default:
                    var fixedString = new FhirString();
                    fixedString.Value   = !string.IsNullOrEmpty(constraint.Value) ? constraint.Value : constraint.DisplayName;
                    newElementDef.Fixed = fixedString;
                    break;
                }
            }

            // Add the type of the element when bound to a value set
            if (hasBinding && schemaObject != null && !string.IsNullOrEmpty(schemaObject.DataType))
            {
                StructureDefinition profile = GetBaseProfile(constraint.Template);
                newElementDef.Type = GetProfileDataTypes(profile, constraint);

                var containedTemplates = (from tcr in constraint.References
                                          join t in this.tdb.Templates on tcr.ReferenceIdentifier equals t.Oid
                                          where tcr.ReferenceType == ConstraintReferenceTypes.Template
                                          select new { Identifier = t.Oid, t.PrimaryContextType });

                // If there is a contained template/profile, make sure it supports a "Reference" type, and then output the profile identifier in the type
                if (containedTemplates.Count() > 0 && newElementDef.Type.Exists(y => y.Code == "Reference" || y.Code == "Extension"))
                {
                    var containedTypes = new List <ElementDefinition.TypeRefComponent>();
                    foreach (var containedTemplate in containedTemplates)
                    {
                        bool isExtension = containedTemplate.PrimaryContextType == "Extension" && newElementDef.Type.Exists(y => y.Code == "Extension");

                        containedTypes.Add(new ElementDefinition.TypeRefComponent()
                        {
                            Code    = isExtension ? "Extension" : "Reference",
                            Profile = new List <string>(new string[] { containedTemplate.Identifier })
                        });
                    }

                    newElementDef.Type = containedTypes;
                }
            }

            // Add the element to the list
            strucDef.Differential.Element.Add(newElementDef);

            // Children
            foreach (var childConstraint in constraint.ChildConstraints.OrderBy(y => y.Order))
            {
                var childSchemaObject = schemaObject != null?schemaObject.Children.SingleOrDefault(y => y.Name == childConstraint.Context) : null;

                CreateElementDefinition(strucDef, childConstraint, childSchemaObject, newSliceName);
            }
        }