private List <ElementDefinition.TypeRefComponent> GetProfileDataTypes(StructureDefinition structure, TemplateConstraint constraint) { if (structure == null || structure.Snapshot == null) { return(null); } string path = constraint.GetFhirPath(); var element = structure.Snapshot.Element.FirstOrDefault(y => y.Path == path); if (element == null) { return(null); } return(element.Type); }
public Template Convert(StructureDefinition strucDef, Template template = null) { if (string.IsNullOrEmpty(strucDef.Type)) { throw new Exception("StructureDefinition.type is required"); } string strucDefDescription = strucDef.Description != null ? strucDef.Description.Value : null; if (template == null) { ImplementationGuide unassignedImplementationGuide = this.tdb.ImplementationGuides.SingleOrDefault(y => y.Name == STU3Helper.DEFAULT_IG_NAME && y.ImplementationGuideTypeId == this.implementationGuideType.Id); if (unassignedImplementationGuide == null) { unassignedImplementationGuide = new ImplementationGuide() { Name = STU3Helper.DEFAULT_IG_NAME, ImplementationGuideType = this.implementationGuideType, Organization = this.tdb.Organizations.Single(y => y.Name == STU3Helper.DEFAULT_ORG_NAME) }; this.tdb.ImplementationGuides.AddObject(unassignedImplementationGuide); } template = new Template() { OwningImplementationGuide = unassignedImplementationGuide, ImplementationGuideType = this.implementationGuideType, Author = this.tdb.Users.Single(y => y.UserName == STU3Helper.DEFAULT_USER_NAME), IsOpen = true }; } // Name if (template.Name != strucDef.Name) { template.Name = strucDef.Name; } // Descrition if (template.Description != strucDefDescription) { template.Description = strucDefDescription; } // Identifier -> Oid string identifier = strucDef.Url; if (string.IsNullOrEmpty(identifier)) { identifier = string.Format(STU3Helper.STRUCDEF_NEW_IDENTIFIER_FORMAT, Guid.NewGuid()); } if (template.Oid != identifier) { template.Oid = identifier; } string fhirBaseType = strucDef.Type != null?strucDef.Type.ToString() : string.Empty; // ConstrainedType -> Template Type TemplateType templateType = this.tdb.TemplateTypes.SingleOrDefault(y => y.ImplementationGuideTypeId == this.implementationGuideType.Id && y.RootContextType == fhirBaseType); if (templateType == null) { throw new Exception("Could not find Template Type for " + strucDef.Type); } if (template.TemplateType != templateType) { template.TemplateType = templateType; } if (template.PrimaryContext != template.TemplateType.RootContext) { template.PrimaryContext = template.TemplateType.RootContext; } if (template.PrimaryContextType != template.TemplateType.RootContextType) { template.PrimaryContextType = template.TemplateType.RootContextType; } // Bookmark template.Bookmark = Template.GenerateBookmark(template.Name, template.TemplateType.Name.ToUpper()); if (strucDef.Snapshot != null && strucDef.Differential == null) { throw new Exception("Trifolia does not support snapshots for DSTU2, yet"); } // Differential.Element -> Constraint if (strucDef.Differential != null) { // Remove all current constraints from the template so that we re-create foreach (var cc in template.ChildConstraints.ToList()) { this.tdb.TemplateConstraints.DeleteObject(cc); } ElementNavigator navigator = new ElementNavigator(strucDef.Differential.Element); TemplateConstraint current = null; if (navigator.MoveToFirstChild() && navigator.MoveToFirstChild()) { while (true) { if (navigator.Current.Slicing != null) { if (!navigator.MoveToNext()) { if (current != null && current.ParentConstraint != null && navigator.MoveToParent()) { current = current.ParentConstraint; } else { break; } } continue; } TemplateConstraint next = new TemplateConstraint(); next.Context = navigator.PathName; next.ParentConstraint = current; next.Order = current != null?current.ChildConstraints.Count() : template.ChildConstraints.Count(y => y.ParentConstraint == null); if (navigator.Elements.Any(y => y.Path == navigator.Path && y.Slicing != null)) { next.IsBranch = true; } template.ChildConstraints.Add(next); string cardinality = string.Format("{0}..{1}", navigator.Current.Min == null ? 0 : navigator.Current.Min, string.IsNullOrEmpty(navigator.Current.Max) ? "*" : navigator.Current.Max); if (next.Cardinality != cardinality) { next.Cardinality = cardinality; } string conformance = cardinality.StartsWith("1") ? "SHALL" : "SHOULD"; if (next.Conformance != conformance) { next.Conformance = conformance; } if (navigator.MoveToFirstChild()) { current = next; continue; } else if (navigator.MoveToNext()) { continue; } else if (navigator.MoveToParent() && navigator.MoveToNext()) { current = current.ParentConstraint; continue; } else { break; } } } } return(template); }
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, constraint); ElementDefinition newElementDef = new ElementDefinition() { ElementId = constraint.Id.ToString(), 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.Type != null ? strucDef.Type.ToString() : null), 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.ContainedTemplate != null; if (constraint.ValueSet != null && valueConformance.IndexOf("NOT") < 0) { hasBinding = true; newElementDef.Binding = new ElementDefinition.BindingComponent() { ValueSet = new ResourceReference() { Reference = constraint.ValueSet.Oid, 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); // If there is a contained template/profile, make sure it supports a "Reference" type, and then output the profile identifier in the type if (constraint.ContainedTemplate != null && newElementDef.Type.Exists(y => y.Code == "Reference" || y.Code == "Extension")) { bool isExtension = constraint.ContainedTemplate.PrimaryContextType == "Extension" && newElementDef.Type.Exists(y => y.Code == "Extension"); var containedTypes = new List <ElementDefinition.TypeRefComponent>(); containedTypes.Add(new ElementDefinition.TypeRefComponent() { Code = isExtension ? "Extension" : "Reference", Profile = constraint.ContainedTemplate.Oid }); 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); } }