public void GetSliceNameTest() { Template t = new Template(); TemplateConstraint tc1 = new TemplateConstraint(); t.ChildConstraints.Add(tc1); tc1.Template = t; tc1.Context = "section"; tc1.IsBranch = true; tc1.Order = 1; TemplateConstraint tc2 = new TemplateConstraint(); t.ChildConstraints.Add(tc2); tc2.Template = t; tc2.Context = "entry"; tc2.ParentConstraint = tc1; tc1.ChildConstraints.Add(tc2); string actual = tc1.GetSliceName(); Assert.AreEqual("section1", actual); actual = tc2.GetSliceName(); Assert.AreEqual("section1", actual); }
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); } }
/// <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); }