public StructureDefinition Convert(Template template, SimpleSchema schema, SummaryType?summaryType = null) { var fhirStructureDef = new fhir_stu3.Hl7.Fhir.Model.StructureDefinition() { Id = template.FhirId(), Name = template.Name, Description = template.Description != null ? new Markdown(template.Description.RemoveInvalidUtf8Characters()) : null, Kind = template.PrimaryContextType == "Extension" ? StructureDefinition.StructureDefinitionKind.ComplexType : StructureDefinition.StructureDefinitionKind.Resource, Url = template.FhirUrl(), Type = template.TemplateType.RootContextType, Context = new List <string> { template.PrimaryContextType }, ContextType = StructureDefinition.ExtensionContext.Resource, Abstract = false, Derivation = StructureDefinition.TypeDerivationRule.Constraint }; // If this is an extension, determine what uses the extension and list them in the // "context" field so that the extension knows where it can be used. foreach (var extension in template.Extensions) { var fhirExtension = Convert(extension); if (fhirExtension != null) { fhirStructureDef.Extension.Add(fhirExtension); } } // Status if (template.Status == null || template.Status.IsDraft || template.Status.IsBallot) { fhirStructureDef.Status = PublicationStatus.Draft; } else if (template.Status.IsPublished) { fhirStructureDef.Status = PublicationStatus.Active; } else if (template.Status.IsDraft) { fhirStructureDef.Status = PublicationStatus.Retired; } // Publisher and Contact if (template.Author != null) { if (!string.IsNullOrEmpty(template.Author.ExternalOrganizationName)) { fhirStructureDef.Publisher = template.Author.ExternalOrganizationName; } var newContact = new ContactDetail(); newContact.Name = string.Format("{0} {1}", template.Author.FirstName, template.Author.LastName); newContact.Telecom.Add(new ContactPoint() { Value = template.Author.Phone, Use = ContactPoint.ContactPointUse.Work, System = ContactPoint.ContactPointSystem.Phone }); newContact.Telecom.Add(new ContactPoint() { Value = template.Author.Email, Use = ContactPoint.ContactPointUse.Work, System = ContactPoint.ContactPointSystem.Email }); fhirStructureDef.Contact.Add(newContact); } // Base profile if (template.ImpliedTemplate != null) { fhirStructureDef.BaseDefinitionElement = new FhirUri(template.ImpliedTemplate.FhirUrl()); } else { fhirStructureDef.BaseDefinitionElement = new FhirUri(string.Format("http://hl7.org/fhir/StructureDefinition/{0}", template.TemplateType.RootContextType)); } // Constraints if (summaryType == null || summaryType == SummaryType.Data) { var differential = new StructureDefinition.DifferentialComponent(); fhirStructureDef.Differential = differential; // Add base element for resource var rootElement = new ElementDefinition(); rootElement.Path = template.PrimaryContextType; rootElement.ElementId = template.PrimaryContextType; differential.Element.Add(rootElement); var rootConstraints = template.ChildConstraints.Where(y => y.ParentConstraint == null).OrderBy(y => y.Order); foreach (var constraint in rootConstraints) { SimpleSchema.SchemaObject schemaObject = null; if (schema != null) { schemaObject = schema.Children.SingleOrDefault(y => y.Name == constraint.Context); } CreateElementDefinition(fhirStructureDef, constraint, schemaObject); } // Slices var slices = template.ChildConstraints.Where(y => y.IsBranch); var sliceGroups = slices.GroupBy(y => y.GetElementPath(template.TemplateType.RootContextType)); int currentSliceGroupCount = 2; // Adds an element that contains "slicing" information for the branch(es) foreach (var sliceGroup in sliceGroups) { ElementDefinition newElementDef = new ElementDefinition(); //newElementDef.ElementId = string.Format("{0}-{1}", template.Id, currentSliceGroupCount.ToString("00")); newElementDef.Path = sliceGroup.Key; newElementDef.ElementId = sliceGroup.First().GetElementPath(template.PrimaryContextType); foreach (var branchConstraint in sliceGroup) { var igSettings = GetIGSettings(branchConstraint); var constraintFormatter = FormattedConstraintFactory.NewFormattedConstraint(this.tdb, igSettings, this.igTypePlugin, branchConstraint); var branchIdentifiers = branchConstraint.ChildConstraints.Where(y => y.IsBranchIdentifier); newElementDef.Definition = constraintFormatter.GetPlainText(false, false, false); newElementDef.Slicing = new ElementDefinition.SlicingComponent() { Rules = template.IsOpen ? ElementDefinition.SlicingRules.Open : ElementDefinition.SlicingRules.Closed }; if (branchIdentifiers.Count() > 0) { newElementDef.Slicing.Discriminator = (from bi in branchIdentifiers select new ElementDefinition.DiscriminatorComponent() { Type = ElementDefinition.DiscriminatorType.Value, Path = bi.GetElementPath(null, branchConstraint) }).ToList(); } else if (branchConstraint.Context == "extension") { newElementDef.Slicing.Discriminator.Add(new ElementDefinition.DiscriminatorComponent() { Type = ElementDefinition.DiscriminatorType.Value, Path = "url" }); } else // If no discriminators are specified, assume the child SHALL constraints are discriminators { var discriminatorConstraints = branchConstraint.ChildConstraints.Where(y => y.Conformance == "SHALL"); var singleValueDiscriminators = discriminatorConstraints.Where(y => !string.IsNullOrEmpty(y.Value)); // If there are constraints that have specific single-value bindings, prefer those if (singleValueDiscriminators.Count() > 0 && singleValueDiscriminators.Count() != discriminatorConstraints.Count()) { discriminatorConstraints = singleValueDiscriminators; } newElementDef.Slicing.Discriminator = (from d in discriminatorConstraints select new ElementDefinition.DiscriminatorComponent() { Type = ElementDefinition.DiscriminatorType.Value, Path = d.GetElementPath(template.PrimaryContextType, branchConstraint) }).ToList(); } } // Find where to insert the slice in the element list var firstElement = fhirStructureDef.Differential.Element.First(y => y.Path == sliceGroup.Key); var firstElementIndex = fhirStructureDef.Differential.Element.IndexOf(firstElement); differential.Element.Insert(firstElementIndex, newElementDef); currentSliceGroupCount++; } } return(fhirStructureDef); }
public StructureDefinition Convert(Template template, SimpleSchema schema, SummaryType?summaryType = null) { string id = template.Id.ToString(); if (template.Oid.StartsWith("http://") || template.Oid.StartsWith("https://")) { id = template.Oid.Substring(template.Oid.LastIndexOf("/") + 1); } var fhirStructureDef = new fhir_stu3.Hl7.Fhir.Model.StructureDefinition() { Id = id, Name = template.Name, Description = !string.IsNullOrEmpty(template.Description) ? new Markdown(template.Description) : null, Kind = StructureDefinition.StructureDefinitionKind.Resource, Url = template.Oid, Type = template.TemplateType.RootContextType, Context = new List <string> { template.PrimaryContextType }, ContextType = template.PrimaryContextType == "Extension" ? StructureDefinition.ExtensionContext.Extension : StructureDefinition.ExtensionContext.Resource, Abstract = false, Derivation = StructureDefinition.TypeDerivationRule.Constraint }; // Extensions foreach (var extension in template.Extensions) { var fhirExtension = Convert(extension); if (fhirExtension != null) { fhirStructureDef.Extension.Add(fhirExtension); } } // Status if (template.Status == null || template.Status.IsDraft || template.Status.IsBallot) { fhirStructureDef.Status = ConformanceResourceStatus.Draft; } else if (template.Status.IsPublished) { fhirStructureDef.Status = ConformanceResourceStatus.Active; } else if (template.Status.IsDraft) { fhirStructureDef.Status = ConformanceResourceStatus.Retired; } // Publisher and Contact if (template.Author != null) { if (!string.IsNullOrEmpty(template.Author.ExternalOrganizationName)) { fhirStructureDef.Publisher = template.Author.ExternalOrganizationName; } var newContact = new StructureDefinition.ContactComponent(); newContact.Name = string.Format("{0} {1}", template.Author.FirstName, template.Author.LastName); newContact.Telecom.Add(new ContactPoint() { Value = template.Author.Phone, Use = ContactPoint.ContactPointUse.Work, System = ContactPoint.ContactPointSystem.Phone }); newContact.Telecom.Add(new ContactPoint() { Value = template.Author.Email, Use = ContactPoint.ContactPointUse.Work, System = ContactPoint.ContactPointSystem.Email }); fhirStructureDef.Contact.Add(newContact); } // Base profile if (template.ImpliedTemplate != null) { fhirStructureDef.BaseDefinitionElement = new FhirUri(template.ImpliedTemplate.Oid); } else { fhirStructureDef.BaseDefinitionElement = new FhirUri(string.Format("http://hl7.org/fhir/StructureDefinition/{0}", template.TemplateType.RootContextType)); } // Constraints if (summaryType == null || summaryType == SummaryType.Data) { var differential = new StructureDefinition.DifferentialComponent(); fhirStructureDef.Differential = differential; // Add base element for resource differential.Element.Add(new ElementDefinition() { ElementId = string.Format("{0}-00001", template.Id.ToString()), Path = template.PrimaryContextType }); foreach (var constraint in template.ChildConstraints.Where(y => y.ParentConstraint == null).OrderBy(y => y.Order)) { var schemaObject = schema.Children.SingleOrDefault(y => y.Name == constraint.Context); CreateElementDefinition(fhirStructureDef, constraint, schemaObject); } // Slices var slices = template.ChildConstraints.Where(y => y.IsBranch); var sliceGroups = slices.GroupBy(y => y.GetElementPath(template.TemplateType.RootContextType)); int currentSliceGroupCount = 2; foreach (var sliceGroup in sliceGroups) { ElementDefinition newElementDef = new ElementDefinition(); newElementDef.ElementId = string.Format("{0}-{1}", template.Id, currentSliceGroupCount.ToString("00000")); newElementDef.Path = sliceGroup.Key; foreach (var branchConstraint in sliceGroup) { var igSettings = GetIGSettings(branchConstraint); var constraintFormatter = FormattedConstraintFactory.NewFormattedConstraint(this.tdb, igSettings, branchConstraint); var branchIdentifiers = branchConstraint.ChildConstraints.Where(y => y.IsBranchIdentifier); newElementDef.Definition = constraintFormatter.GetPlainText(false, false, false); newElementDef.Slicing = new ElementDefinition.SlicingComponent() { Discriminator = (from bi in branchIdentifiers select bi.GetElementPath(template.TemplateType.RootContextType)), Rules = template.IsOpen ? ElementDefinition.SlicingRules.Open : ElementDefinition.SlicingRules.Closed }; // If no discriminators are specified, assume the child SHALL constraints are discriminators if (newElementDef.Slicing.Discriminator.Count() == 0) { var discriminatorConstraints = branchConstraint.ChildConstraints.Where(y => y.Conformance == "SHALL"); // If the slice referencing a contained template, use the constraints of the contained template instead of the // direct constraints of the branch if (branchConstraint.ContainedTemplate != null) { discriminatorConstraints = branchConstraint.ContainedTemplate.ChildConstraints.Where(y => y.ParentConstraint == null & y.Conformance == "SHALL"); } var singleValueDiscriminators = discriminatorConstraints.Where(y => !string.IsNullOrEmpty(y.Value)); // If there are constraints that have specific single-value bindings, prefer those if (singleValueDiscriminators.Count() > 0 && singleValueDiscriminators.Count() != discriminatorConstraints.Count()) { discriminatorConstraints = singleValueDiscriminators; } newElementDef.Slicing.Discriminator = discriminatorConstraints.Select(y => y.GetElementPath(template.PrimaryContextType)); } } // Find where to insert the slice in the element list var firstElement = fhirStructureDef.Differential.Element.First(y => y.Path == sliceGroup.Key); var firstElementIndex = fhirStructureDef.Differential.Element.IndexOf(firstElement); differential.Element.Insert(firstElementIndex, newElementDef); } } return(fhirStructureDef); }