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);
        }
Ejemplo n.º 2
0
        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);
        }