/// <summary>
 /// Search for Resources of a certain type that match the given criteria
 /// </summary>
 /// <param name="criteria">Optional. The search parameters to filter the resources on. Each
 /// given string is a combined key/value pair (separated by '=')</param>
 /// <param name="includes">Optional. A list of include paths</param>
 /// <param name="pageSize">Optional. Asks server to limit the number of entries per page returned</param>
 /// <param name="summary">Optional. Whether to include only return a summary of the resources in the Bundle</param>
 /// <typeparam name="TResource">The type of resource to list</typeparam>
 /// <returns>A Bundle with all resources found by the search, or an empty Bundle if none were found.</returns>
 /// <remarks>All parameters are optional, leaving all parameters empty will return an unfiltered list
 /// of all resources of the given Resource type</remarks>
 public Bundle Search <TResource>(string[] criteria = null, string[] includes = null, int?pageSize = null, SummaryType?summary = null)
     where TResource : Resource, new()
 {
     // [WMR 20160421] GetResourceNameForType is obsolete
     // return Search(ModelInfo.GetResourceNameForType(typeof(TResource)), criteria, includes, pageSize, summary);
     return(Search(ModelInfo.GetFhirTypeNameForType(typeof(TResource)), criteria, includes, pageSize, summary));
 }
        public IHttpActionResult GetTemplates(
            [FromUri(Name = "_id")] int?templateId           = null,
            [FromUri(Name = "name")] string name             = null,
            [FromUri(Name = "_summary")] SummaryType?summary = null)
        {
            var uri       = HttpContext.Current != null && HttpContext.Current.Request != null ? HttpContext.Current.Request.Url : new Uri(AppSettings.DefaultBaseUrl);
            var templates = this.tdb.Templates.Where(y => y.TemplateType.ImplementationGuideType == this.implementationGuideType);
            StructureDefinitionExporter exporter = new StructureDefinitionExporter(this.tdb, uri.Scheme, uri.Authority);

            if (!CheckPoint.Instance.IsDataAdmin)
            {
                User currentUser = CheckPoint.Instance.GetUser(this.tdb);
                templates = (from t in templates
                             join vtp in this.tdb.ViewTemplatePermissions on t.Id equals vtp.TemplateId
                             where vtp.UserId == currentUser.Id
                             select t);
            }

            if (templateId != null)
            {
                templates = templates.Where(y => y.Id == templateId);
            }

            if (!string.IsNullOrEmpty(name))
            {
                templates = templates.Where(y => y.Name.ToLower().Contains(name.ToLower()));
            }

            Bundle bundle = new Bundle()
            {
                Type = Bundle.BundleType.BatchResponse
            };

            foreach (var template in templates)
            {
                SimpleSchema schema = SimplifiedSchemaContext.GetSimplifiedSchema(HttpContext.Current, template.ImplementationGuideType);
                schema = schema.GetSchemaFromContext(template.PrimaryContextType);

                bool isMatch = true;
                StructureDefinition strucDef = exporter.Convert(template, schema, summary);
                var fullUrl = string.Format("{0}://{1}/api/FHIR2/StructureDefinition/{2}",
                                            this.Request.RequestUri.Scheme,
                                            this.Request.RequestUri.Authority,
                                            template.Id);

                // Skip adding the structure definition to the response if a criteria rules it out
                foreach (var queryParam in this.Request.GetQueryNameValuePairs())
                {
                    if (queryParam.Key == "_id" || queryParam.Key == "name" || queryParam.Key == "_format" || queryParam.Key == "_summary")
                    {
                        continue;
                    }

                    if (queryParam.Key.Contains("."))
                    {
                        throw new NotSupportedException(App_GlobalResources.TrifoliaLang.FHIRSearchCriteriaNotSupported);
                    }

                    var propertyDef = strucDef.GetType().GetProperty(queryParam.Key, System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);

                    if (propertyDef == null)
                    {
                        continue;
                    }

                    var value       = propertyDef.GetValue(strucDef);
                    var valueString = value != null?value.ToString() : string.Empty;

                    if (valueString != queryParam.Value)
                    {
                        isMatch = false;
                    }
                }

                if (isMatch)
                {
                    bundle.AddResourceEntry(strucDef, fullUrl);
                }
            }

            return(Content <Bundle>(HttpStatusCode.OK, bundle));
        }
        private SearchParams toQuery(string[] criteria, string[] includes, int?pageSize, SummaryType?summary)
        {
            var q = new SearchParams();

            q.Count = pageSize;

            if (includes != null)
            {
                foreach (var inc in includes)
                {
                    q.Include.Add(inc);
                }
            }

            if (criteria != null)
            {
                foreach (var crit in criteria)
                {
                    var keyVal = crit.SplitLeft('=');
                    q.Add(keyVal.Item1, keyVal.Item2);
                }
            }

            if (summary != null)
            {
                q.Summary = summary.Value;
            }

            return(q);
        }
示例#4
0
        /// <summary>
        /// Converts a Trifolia ValueSet model to a FHIR ValueSet model.
        /// </summary>
        /// <param name="valueSet">The Trifolia ValueSet model to convert to a FHIR model</param>
        /// <param name="summaryType">Does not populate certain fields when a summaryType is specified.</param>
        /// <param name="publishedValueSets">Optional list of ValueSets that are used by a published implementation guide. If not specified, queries the database for implementation guides that this value set may be published under.</param>
        /// <returns>A FHIR ValueSet model</returns>
        public FhirValueSet Convert(ValueSet valueSet, SummaryType?summaryType = null, IEnumerable <ValueSet> publishedValueSets = null, string baseUrl = null)
        {
            bool usedByPublishedIgs = false;

            if (publishedValueSets == null)
            {
                var implementationGuides = (from tc in valueSet.Constraints
                                            join t in this.tdb.Templates on tc.TemplateId equals t.Id
                                            select t.OwningImplementationGuide);
                usedByPublishedIgs = implementationGuides.Count(y => y.PublishStatus != null && y.PublishStatus.IsPublished) > 0;
            }
            else
            {
                usedByPublishedIgs = publishedValueSets.Contains(valueSet);
            }

            FhirValueSet fhirValueSet = new FhirValueSet()
            {
                Meta = new Meta()
                {
                    ElementId = valueSet.Id.ToString()
                },
                Id          = valueSet.GetFhirId(),
                Name        = valueSet.Name,
                Status      = usedByPublishedIgs ? PublicationStatus.Active : PublicationStatus.Draft,
                Description = new Markdown(valueSet.Description),
                Url         = valueSet.GetIdentifier(ValueSetIdentifierTypes.HTTP)
            };

            // Handle urn:oid: and urn:hl7ii: identifiers differently if a base url is provided
            // baseUrl is most likely provided when within the context of an implementation guide
            if (fhirValueSet.Url != null)
            {
                if (fhirValueSet.Url.StartsWith("urn:oid:") && !string.IsNullOrEmpty(baseUrl))
                {
                    fhirValueSet.Url = baseUrl.TrimEnd('/') + "/ValueSet/" + fhirValueSet.Url.Substring(8);
                }
                else if (fhirValueSet.Url.StartsWith("urn:hl7ii:") && !string.IsNullOrEmpty(baseUrl))
                {
                    fhirValueSet.Url = baseUrl.TrimEnd('/') + "/ValueSet/" + fhirValueSet.Url.Substring(10);
                }
            }

            List <ValueSetMember> activeMembers = valueSet.GetActiveMembers(DateTime.Now);

            if (activeMembers.Count > 0)
            {
                // If the value set was created in Trifolia, then Trifolia contains the definition
                // and it should be represented by <compose>
                if (valueSet.ImportSource == null)
                {
                    // Compose
                    var compose = new FhirValueSet.ComposeComponent();
                    fhirValueSet.Compose = compose;

                    foreach (var groupedMember in activeMembers.GroupBy(y => y.CodeSystem, y => y))
                    {
                        var include = new FhirValueSet.ConceptSetComponent();
                        compose.Include.Add(include);

                        include.System = groupedMember.Key.Oid;

                        foreach (var member in groupedMember)
                        {
                            include.Concept.Add(new FhirValueSet.ConceptReferenceComponent()
                            {
                                Code    = member.Code,
                                Display = member.DisplayName
                            });
                        }
                    }
                }
                else
                {
                    // If the value set was imported, then we have the expansion,
                    // but we don't have the defintion (the <compose>).
                    var expansion = new FhirValueSet.ExpansionComponent();
                    fhirValueSet.Expansion = expansion;
                    expansion.Identifier   = fhirValueSet.Url;
                    expansion.Total        = activeMembers.Count;

                    if (valueSet.LastUpdate != null)
                    {
                        expansion.TimestampElement = new FhirDateTime(valueSet.LastUpdate.Value);
                    }
                    else
                    {
                        expansion.TimestampElement = new FhirDateTime(DateTime.Now);
                    }

                    expansion.Contains = (from m in activeMembers
                                          select new FhirValueSet.ContainsComponent()
                    {
                        System = m.CodeSystem.Oid,
                        Code = m.Code,
                        Display = m.DisplayName
                    }).ToList();
                }
            }

            return(fhirValueSet);
        }
示例#5
0
        private SearchParams toQuery(string[] criteria, string[] includes, int?pageSize, SummaryType?summary, string[] revIncludes)
        {
            var q = new SearchParams()
            {
                Count = pageSize
            };

            if (includes != null)
            {
                foreach (var inc in includes)
                {
                    q.Include.Add(inc);
                }
            }

            if (revIncludes != null)
            {
                foreach (var revInc in revIncludes)
                {
                    q.RevInclude.Add(revInc);
                }
            }

            if (criteria != null)
            {
                foreach (var crit in criteria)
                {
                    var keyVal = crit.SplitLeft('=');

                    if (string.IsNullOrEmpty(keyVal.Item1) || string.IsNullOrEmpty(keyVal.Item2))
                    {
                        throw Error.Argument("criteria", "Argument should be of the form <key>=<value>");
                    }

                    q.Add(keyVal.Item1, keyVal.Item2);
                }
            }

            if (summary != null)
            {
                q.Summary = summary.Value;
            }

            return(q);
        }
        public Bundle GetImplementationGuides(SummaryType?summary = null, string include = null, int?implementationGuideId = null, string name = null)
        {
            // TODO: Should not be using constant string for IG type name to find templates... Not sure how else to identify FHIR DSTU1 templates though
            var implementationGuides = this.tdb.ImplementationGuides.Where(y => y.ImplementationGuideTypeId == this.implementationGuideType.Id);

            if (!CheckPoint.Instance.IsDataAdmin)
            {
                User currentUser = CheckPoint.Instance.GetUser(this.tdb);
                implementationGuides = (from ig in implementationGuides
                                        join igp in this.tdb.ImplementationGuidePermissions on ig.Id equals igp.UserId
                                        where igp.UserId == currentUser.Id
                                        select ig);
            }

            if (implementationGuideId != null)
            {
                implementationGuides = implementationGuides.Where(y => y.Id == implementationGuideId);
            }

            if (!string.IsNullOrEmpty(name))
            {
                implementationGuides = implementationGuides.Where(y => y.Name.ToLower().Contains(name.ToLower()));
            }

            Bundle bundle = new Bundle()
            {
                Type = Bundle.BundleType.BatchResponse
            };

            foreach (var ig in implementationGuides)
            {
                FhirImplementationGuide fhirImplementationGuide = Convert(ig, summary);

                // Add the IG before the templates
                bundle.AddResourceEntry(fhirImplementationGuide, this.GetFullUrl(ig));

                // TODO: Need to implement a more sophisticated approach to parsing "_include"
                if (!string.IsNullOrEmpty(include) && include == "ImplementationGuide:resource")
                {
                    List <Template> templates = ig.GetRecursiveTemplates(this.tdb, inferred: true);

                    /*
                     * // TODO: Add additional query parameters for indicating parent template ids and categories?
                     * IGSettingsManager igSettings = new IGSettingsManager(this.tdb, ig.Id);
                     * string templateBundleXml = FHIRExporter.GenerateExport(this.tdb, templates, igSettings);
                     * Bundle templateBundle = (Bundle)FhirParser.ParseResourceFromXml(templateBundleXml);
                     *
                     * var templateEntries = templateBundle.Entry.Where(y =>
                     *  y.Resource.ResourceType != ResourceType.ImplementationGuide &&
                     *  y.Resource.Id != fhirImplementationGuide.Id);
                     *
                     * // TODO: Make sure that if multiple IGs are returned, that there are distinct bundle entries
                     * // (no duplicate template/profile entries that are referenced by two separate IGs)
                     * bundle.Entry.AddRange(templateEntries);
                     */

                    StructureDefinitionExporter strucDefExporter = new StructureDefinitionExporter(this.tdb, this.scheme, this.authority);
                    foreach (var template in templates)
                    {
                        var templateSchema = this.schema.GetSchemaFromContext(template.PrimaryContextType);
                        var strucDef       = strucDefExporter.Convert(template, schema);
                        bundle.AddResourceEntry(strucDef, this.GetFullUrl(template));
                    }
                }
            }

            return(bundle);
        }
        public StructureDefinition Convert(Template template, SimpleSchema schema, SummaryType?summaryType = null)
        {
            var fhirStructureDef = new fhir_latest.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);
        }
示例#8
0
 /// <summary>
 /// Search for Resources of a certain type that match the given criteria
 /// </summary>
 /// <param name="criteria">Optional. The search parameters to filter the resources on. Each
 /// given string is a combined key/value pair (separated by '=')</param>
 /// <param name="includes">Optional. A list of include paths</param>
 /// <param name="pageSize">Optional. Asks server to limit the number of entries per page returned</param>
 /// <param name="summary">Optional. Whether to include only return a summary of the resources in the Bundle</param>
 /// <param name="revIncludes">Optional. A list of reverse include paths</param>
 /// <typeparam name="TResource">The type of resource to list</typeparam>
 /// <returns>A Bundle with all resources found by the search, or an empty Bundle if none were found.</returns>
 /// <remarks>All parameters are optional, leaving all parameters empty will return an unfiltered list
 /// of all resources of the given Resource type</remarks>
 public Task <Bundle> SearchUsingPostAsync <TResource>(string[] criteria   = null, string[] includes    = null, int?pageSize = null,
                                                       SummaryType?summary = null, string[] revIncludes = null)
     where TResource : Resource, new()
 {
     return(SearchUsingPostAsync(ModelInfo.GetFhirTypeNameForType(typeof(TResource)), criteria, includes, pageSize, summary, revIncludes));
 }
示例#9
0
 /// <summary>
 /// Search for Resources of a certain type that match the given criteria
 /// </summary>
 /// <param name="criteria">Optional. The search parameters to filter the resources on. Each
 /// given string is a combined key/value pair (separated by '=')</param>
 /// <param name="includes">Optional. A list of include paths</param>
 /// <param name="pageSize">Optional. Asks server to limit the number of entries per page returned</param>
 /// <param name="summary">Optional. Whether to include only return a summary of the resources in the Bundle</param>
 /// <param name="revIncludes">Optional. A list of reverse include paths</param>
 /// <typeparam name="TResource">The type of resource to list</typeparam>
 /// <returns>A Bundle with all resources found by the search, or an empty Bundle if none were found.</returns>
 /// <remarks>All parameters are optional, leaving all parameters empty will return an unfiltered list
 /// of all resources of the given Resource type</remarks>
 public Bundle SearchUsingPost <TResource>(string[] criteria   = null, string[] includes    = null, int?pageSize = null,
                                           SummaryType?summary = null, string[] revIncludes = null)
     where TResource : Resource, new()
 {
     return(SearchUsingPostAsync <TResource>(criteria, includes, pageSize, summary, revIncludes).WaitResult());
 }
        public StructureDefinition Convert(Template template, SimpleSchema schema, SummaryType?summaryType = null)
        {
            StructureDefinition fhirStructureDef = new StructureDefinition()
            {
                Name            = template.Name,
                Description     = template.Description,
                Kind            = StructureDefinition.StructureDefinitionKind.Resource,
                Url             = template.Oid,
                ConstrainedType = template.TemplateType.RootContextType,
                Abstract        = false
            };

            // 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.StructureDefinitionContactComponent();
                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.Base = string.Format("StructureDefinition/{0}", template.ImpliedTemplate.Id);
            }
            else
            {
                fhirStructureDef.Base = string.Format("http://hl7.org/fhir/StructureDefinition/{0}", template.TemplateType.RootContextType);
            }

            // Constraints
            if (summaryType == null || summaryType == SummaryType.Data)
            {
                fhirStructureDef.Differential = new StructureDefinition.StructureDefinitionDifferentialComponent();

                // Add base element for resource
                fhirStructureDef.Differential.Element.Add(new ElementDefinition()
                {
                    Path = template.TemplateType.RootContextType
                });

                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));

                foreach (var sliceGroup in sliceGroups)
                {
                    ElementDefinition newElementDef = new ElementDefinition();
                    newElementDef.Path = sliceGroup.Key;

                    foreach (var branchConstraint in sliceGroup)
                    {
                        var branchIdentifiers = branchConstraint.ChildConstraints.Where(y => y.IsBranchIdentifier);
                        newElementDef.Slicing = new ElementDefinition.ElementDefinitionSlicingComponent()
                        {
                            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)
                        {
                            newElementDef.Slicing.Discriminator = (from cc in branchConstraint.ChildConstraints
                                                                   where cc.Conformance == "SHALL"
                                                                   select cc.GetElementPath(template.TemplateType.RootContextType));
                        }
                    }

                    // 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);
                    fhirStructureDef.Differential.Element.Insert(firstElementIndex, newElementDef);
                }
            }

            return(fhirStructureDef);
        }
示例#11
0
        /// <summary>
        ///  Search for Resources of a certain type that match the given criteria
        /// </summary>
        /// <param name="type">The type of resource to search for</param>
        /// <param name="q">Optional. The search parameters to filter the resources on. Each
        /// given string is a combined key/value pair (separated by '=')</param>
        /// <param name="includes">Optional. A list of include paths</param>
        /// <param name="pageSize">Optional. Asks server to limit the number of entries per page returned</param>
        /// <param name="summary">>Optional. Whether to include only return a summary of the resources in the Bundle</param>
        /// <returns>A List with all resource Ids found by the search, or an empty List if none were found.</returns>
        public List <String> FilteredGetIds(string type, int page = 1, string[] q = null, string[] includes = null, int?pageSize = null, SummaryType?summary = null)
        {
            List <String> result = new List <String>();

            if (string.IsNullOrWhiteSpace(type))
            {
                return(result);
            }
            var bundle = _client.Search(type);

            while (bundle != null)
            {
                foreach (var entry in bundle.Entry)
                {
                    result.Add(entry.Resource.Id);
                }
                bundle = _client.Continue(bundle);
            }
            return(result);
        }
 public PyroSearchParameters()
 {
     this.SummaryType = null;
 }
示例#13
0
        public FhirImplementationGuide Convert(ImplementationGuide ig, SummaryType?summaryType = null, bool includeVocabulary = true)
        {
            var fhirImplementationGuide = new FhirImplementationGuide()
            {
                Id   = ig.Id.ToString(),
                Name = ig.Name,
                Url  = string.Format("ImplementationGuide/{0}", ig.Id)
            };

            // Status
            if (ig.PublishStatus == PublishStatus.GetPublishedStatus(this.tdb))
            {
                fhirImplementationGuide.Status = ConformanceResourceStatus.Active;
            }
            else if (ig.PublishStatus == PublishStatus.GetRetiredStatus(this.tdb) || ig.PublishStatus == PublishStatus.GetDeprecatedStatus(this.tdb))
            {
                fhirImplementationGuide.Status = ConformanceResourceStatus.Retired;
            }
            else
            {
                fhirImplementationGuide.Status = ConformanceResourceStatus.Draft;
            }

            if (summaryType == null || summaryType == SummaryType.Data)
            {
                // Package
                FhirImplementationGuide.PackageComponent package = new FhirImplementationGuide.PackageComponent();
                package.Name = "Profiles in this Implementation Guide";
                fhirImplementationGuide.Package.Add(package);

                // Page: Create a page for the implementation guide. This is required by the fhir ig publisher
                fhirImplementationGuide.Page        = new FhirImplementationGuide.PageComponent();
                fhirImplementationGuide.Page.Kind   = FhirImplementationGuide.GuidePageKind.Page;
                fhirImplementationGuide.Page.Title  = ig.GetDisplayName();
                fhirImplementationGuide.Page.Source = string.Format("{0}://{1}/IG/View/{2}", this.scheme, this.authority, ig.Id);

                // Add profiles to the implementation guide
                List <Template> templates        = ig.GetRecursiveTemplates(this.tdb, inferred: false);
                var             profileResources = (from t in templates
                                                    select new FhirImplementationGuide.ResourceComponent()
                {
                    Example = false,
                    Source = new ResourceReference()
                    {
                        Reference = string.Format("StructureDefinition/{0}", t.FhirId()),
                        Display = t.Name
                    }
                });
                package.Resource.AddRange(profileResources);

                if (includeVocabulary)
                {
                    // Add value sets to the implementation guide
                    var valueSets = (from t in templates
                                     join tc in this.tdb.TemplateConstraints on t.Id equals tc.TemplateId
                                     where tc.ValueSet != null
                                     select tc.ValueSet).Distinct().ToList();
                    var valueSetResources = (from vs in valueSets
                                             select new FhirImplementationGuide.ResourceComponent()
                    {
                        Example = false,
                        Source = new ResourceReference()
                        {
                            Reference = string.Format("ValueSet/{0}", vs.Id.ToString()),
                            Display = vs.Name
                        }
                    });
                    package.Resource.AddRange(valueSetResources);
                }

                // Add each of the individual FHIR resources added as files to the IG
                foreach (var file in ig.Files)
                {
                    var      fileData = file.GetLatestData();
                    Resource resource = null;

                    try
                    {
                        string fileContent = System.Text.Encoding.UTF8.GetString(fileData.Data);

                        if (file.MimeType == "application/xml" || file.MimeType == "text/xml")
                        {
                            resource = FhirParser.ParseResourceFromXml(fileContent);
                        }
                        else if (file.MimeType == "application/json")
                        {
                            resource = FhirParser.ParseResourceFromJson(fileContent);
                        }
                    }
                    catch
                    {
                    }

                    if (resource == null || string.IsNullOrEmpty(resource.Id))
                    {
                        continue;
                    }

                    var packageFile = new FhirImplementationGuide.ResourceComponent()
                    {
                        Example = false,
                        Source  = new ResourceReference()
                        {
                            Reference = string.Format("{0}/{1}", resource.ResourceType, resource.Id),
                            Display   = GetResourceName(resource, file.FileName)
                        }
                    };

                    package.Resource.Add(packageFile);
                }

                // Add each of the samples generated for the template/profile
                var templateExamples = (from t in templates
                                        join ts in this.tdb.TemplateSamples on t.Id equals ts.TemplateId
                                        select new { Template = t, Sample = ts });

                foreach (var templateExample in templateExamples)
                {
                    Resource resource = null;

                    try
                    {
                        resource = FhirParser.ParseResourceFromXml(templateExample.Sample.XmlSample);
                    }
                    catch
                    {
                    }

                    try
                    {
                        if (resource == null)
                        {
                            resource = FhirParser.ParseResourceFromJson(templateExample.Sample.XmlSample);
                        }
                    }
                    catch
                    {
                    }

                    if (resource == null || string.IsNullOrEmpty(resource.Id))
                    {
                        continue;
                    }

                    var packageExample = new FhirImplementationGuide.ResourceComponent()
                    {
                        Example = true,
                        Source  = new ResourceReference()
                        {
                            Reference = string.Format("{0}/{1}", resource.ResourceType, resource.Id),
                            Display   = GetResourceName(resource, templateExample.Sample.Name)
                        }
                    };

                    package.Resource.Add(packageExample);
                }
            }

            return(fhirImplementationGuide);
        }
        /// <summary>
        /// Serialize the reply
        /// </summary>
        public void SerializeResponse(RestResponseMessage responseMessage, object[] parameters, object result)
        {
            try
            {
                // Outbound control
                var    httpRequest = RestOperationContext.Current.IncomingRequest;
                string accepts     = httpRequest.Headers["Accept"],
                       contentType = httpRequest.Headers["Content-Type"],
                       formatParm  = httpRequest.QueryString["_format"];

                var isOutputPretty = httpRequest.QueryString["_pretty"] == "true";

                SummaryType?summaryType = SummaryType.False;
                if (httpRequest.QueryString["_summary"] != null)
                {
                    summaryType = EnumUtility.ParseLiteral <SummaryType>(httpRequest.QueryString["_summary"], true);
                }

                if (accepts == "*/*") // Any = null
                {
                    accepts = null;
                }

                contentType = accepts ?? contentType ?? formatParm;

                // No specified content type
                if (string.IsNullOrEmpty(contentType))
                {
                    contentType = this.m_configuration.DefaultResponseFormat == FhirResponseFormatConfiguration.Json ? "application/fhir+json" : "application/fhir+xml";
                }

                var charset = ContentType.GetCharSetFromHeaderValue(contentType);
                var format  = ContentType.GetMediaTypeFromHeaderValue(contentType);

                if (result is Base baseObject)
                {
                    var ms = new MemoryStream();
                    // The request was in JSON or the accept is JSON
                    switch (format)
                    {
                    case "application/fhir+xml":
                        using (var xw = XmlWriter.Create(ms, new XmlWriterSettings
                        {
                            Encoding = new UTF8Encoding(false),
                            Indent = isOutputPretty
                        }))
                        {
                            new FhirXmlSerializer().Serialize(baseObject, xw, summaryType.Value);
                        }

                        break;

                    case "application/fhir+json":
                        using (var sw = new StreamWriter(ms, new UTF8Encoding(false), 1024, true))
                            using (var jw = new JsonTextWriter(sw)
                            {
                                Formatting = isOutputPretty ? Formatting.Indented : Formatting.None,
                                DateFormatHandling = DateFormatHandling.IsoDateFormat
                            })
                            {
                                new FhirJsonSerializer(new SerializerSettings
                                {
                                    Pretty = isOutputPretty
                                }).Serialize(baseObject, jw);
                            }

                        break;

                    default:
                        throw new FhirException((HttpStatusCode)406, OperationOutcome.IssueType.NotSupported, $"{contentType} not supported");
                    }

                    ms.Seek(0, SeekOrigin.Begin);
                    responseMessage.Body = ms;
                }
                else if (result == null)
                {
                    responseMessage.StatusCode = 204; // no content
                }
                else
                {
                    throw new InvalidOperationException("FHIR return values must inherit from Base");
                }

                RestOperationContext.Current.OutgoingResponse.ContentType = contentType;
                RestOperationContext.Current.OutgoingResponse.AppendHeader("X-PoweredBy", string.Format("{0} v{1} ({2})", Assembly.GetEntryAssembly().GetName().Name, Assembly.GetEntryAssembly().GetName().Version, Assembly.GetEntryAssembly().GetCustomAttribute <AssemblyInformationalVersionAttribute>()?.InformationalVersion));
                RestOperationContext.Current.OutgoingResponse.AppendHeader("X-GeneratedOn", DateTime.Now.ToString("o"));
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(EventLevel.Error, e.ToString());
                throw;
            }
        }
        /// <summary>
        /// Search for Resources of a certain type that match the given criteria
        /// </summary>
        /// <param name="resource">The type of resource to search for</param>
        /// <param name="criteria">Optional. The search parameters to filter the resources on. Each
        /// given string is a combined key/value pair (separated by '=')</param>
        /// <param name="includes">Optional. A list of include paths</param>
        /// <param name="pageSize">Optional. Asks server to limit the number of entries per page returned</param>
        /// <param name="summary">Optional. Whether to include only return a summary of the resources in the Bundle</param>
        /// <returns>A Bundle with all resources found by the search, or an empty Bundle if none were found.</returns>
        /// <remarks>All parameters are optional, leaving all parameters empty will return an unfiltered list
        /// of all resources of the given Resource type</remarks>
        public Bundle Search(string resource, string[] criteria = null, string[] includes = null, int?pageSize = null, SummaryType?summary = null)
        {
            if (resource == null)
            {
                throw Error.ArgumentNull(nameof(resource));
            }

            return(Search(toQuery(criteria, includes, pageSize, summary), resource));
        }
示例#16
0
 /// <summary>
 /// Search for Resources of a certain type that match the given criteria
 /// </summary>
 /// <param name="resource">The type of resource to search for</param>
 /// <param name="criteria">Optional. The search parameters to filter the resources on. Each
 /// given string is a combined key/value pair (separated by '=')</param>
 /// <param name="includes">Optional. A list of include paths</param>
 /// <param name="pageSize">Optional. Asks server to limit the number of entries per page returned</param>
 /// <param name="summary">Optional. Whether to include only return a summary of the resources in the Bundle</param>
 /// <param name="revIncludes">Optional. A list of reverse include paths</param>
 /// <returns>A Bundle with all resources found by the search, or an empty Bundle if none were found.</returns>
 /// <remarks>All parameters are optional, leaving all parameters empty will return an unfiltered list
 /// of all resources of the given Resource type</remarks>
 public Bundle Search(string resource, string[] criteria = null, string[] includes = null, int?pageSize = null,
                      SummaryType?summary = null, string[] revIncludes             = null)
 {
     return(SearchAsync(resource, criteria, includes, pageSize, summary, revIncludes).WaitResult());
 }
示例#17
0
        /// <summary>
        /// Converts a Trifolia ValueSet model to a FHIR ValueSet model.
        /// </summary>
        /// <param name="valueSet">The Trifolia ValueSet model to convert to a FHIR model</param>
        /// <param name="summaryType">Does not populate certain fields when a summaryType is specified.</param>
        /// <param name="publishedValueSets">Optional list of ValueSets that are used by a published implementation guide. If not specified, queries the database for implementation guides that this value set may be published under.</param>
        /// <returns>A FHIR ValueSet model</returns>
        public FhirValueSet Convert(ValueSet valueSet, SummaryType?summaryType = null, IEnumerable <ValueSet> publishedValueSets = null)
        {
            bool usedByPublishedIgs = false;

            if (publishedValueSets == null)
            {
                var implementationGuides = (from tc in valueSet.Constraints
                                            join t in this.tdb.Templates on tc.TemplateId equals t.Id
                                            select t.OwningImplementationGuide);
                usedByPublishedIgs = implementationGuides.Count(y => y.PublishStatus != null && y.PublishStatus.IsPublished) > 0;
            }
            else
            {
                usedByPublishedIgs = publishedValueSets.Contains(valueSet);
            }

            FhirValueSet fhirValueSet = new FhirValueSet()
            {
                Id          = valueSet.GetFhirId(),
                Name        = valueSet.Name,
                Status      = usedByPublishedIgs ? ConformanceResourceStatus.Active : ConformanceResourceStatus.Draft,
                Description = new Markdown(valueSet.Description),
                Url         = valueSet.Oid
            };

            if (summaryType == null || summaryType == SummaryType.Data)
            {
                var activeMembers = valueSet.GetActiveMembers(DateTime.Now);

                if (activeMembers.Count > 0)
                {
                    // Compose
                    var compose = new FhirValueSet.ComposeComponent();
                    fhirValueSet.Compose = compose;

                    foreach (var groupedMember in activeMembers.GroupBy(y => y.CodeSystem, y => y))
                    {
                        var include = new FhirValueSet.ConceptSetComponent();
                        compose.Include.Add(include);

                        include.System = groupedMember.Key.Oid;

                        foreach (var member in groupedMember)
                        {
                            include.Concept.Add(new FhirValueSet.ConceptReferenceComponent()
                            {
                                Code    = member.Code,
                                Display = member.DisplayName
                            });
                        }
                    }

                    // Expansion
                    var expansion = new FhirValueSet.ExpansionComponent();
                    expansion.Identifier   = string.Format("urn:uuid:{0}", Guid.NewGuid());
                    expansion.Timestamp    = FhirDateTime.Now().ToString();
                    fhirValueSet.Expansion = expansion;

                    foreach (ValueSetMember vsMember in activeMembers)
                    {
                        var fhirMember = new FhirValueSet.ContainsComponent()
                        {
                            System  = STU3Helper.FormatIdentifier(vsMember.CodeSystem.Oid),
                            Code    = vsMember.Code,
                            Display = vsMember.DisplayName
                        };

                        expansion.Contains.Add(fhirMember);
                    }
                }
            }

            return(fhirValueSet);
        }
示例#18
0
 /// <summary>
 /// Search for Resources across the whole server that match the given criteria
 /// </summary>
 /// <param name="criteria">Optional. The search parameters to filter the resources on. Each
 /// given string is a combined key/value pair (separated by '=')</param>
 /// <param name="includes">Optional. A list of include paths</param>
 /// <param name="pageSize">Optional. Asks server to limit the number of entries per page returned</param>
 /// <param name="summary">Optional. Whether to include only return a summary of the resources in the Bundle</param>
 /// <param name="revIncludes">Optional. A list of reverse include paths</param>
 /// <returns>A Bundle with all resources found by the search, or an empty Bundle if none were found.</returns>
 /// <remarks>All parameters are optional, leaving all parameters empty will return an unfiltered list
 /// of all resources of the given Resource type</remarks>
 public Task <Bundle> WholeSystemSearchUsingPostAsync(string[] criteria   = null, string[] includes    = null, int?pageSize = null,
                                                      SummaryType?summary = null, string[] revIncludes = null)
 {
     return(SearchUsingPostAsync(toQuery(criteria, includes, pageSize, summary, revIncludes)));
 }
        public FhirImplementationGuide Convert(ImplementationGuide ig, SummaryType?summaryType = null, bool includeVocabulary = true)
        {
            var parserSettings = new fhir_latest.Hl7.Fhir.Serialization.ParserSettings();

            parserSettings.AcceptUnknownMembers        = true;
            parserSettings.AllowUnrecognizedEnums      = true;
            parserSettings.DisallowXsiAttributesOnRoot = false;
            var fhirXmlParser  = new FhirXmlParser(parserSettings);
            var fhirJsonParser = new FhirJsonParser(parserSettings);

            string url = string.Format("ImplementationGuide/{0}", ig.Id);

            if (!string.IsNullOrEmpty(ig.Identifier) && (ig.Identifier.StartsWith("http://") || ig.Identifier.StartsWith("https://")))
            {
                url = ig.Identifier.TrimEnd('/') + "/" + url.TrimStart('/');
            }

            var fhirImplementationGuide = new FhirImplementationGuide()
            {
                Id   = ig.Id.ToString(),
                Name = ig.Name,
                Url  = url
            };

            // Status
            if (ig.PublishStatus == PublishStatus.GetPublishedStatus(this.tdb))
            {
                fhirImplementationGuide.Status = PublicationStatus.Active;
            }
            else if (ig.PublishStatus == PublishStatus.GetRetiredStatus(this.tdb) || ig.PublishStatus == PublishStatus.GetDeprecatedStatus(this.tdb))
            {
                fhirImplementationGuide.Status = PublicationStatus.Retired;
            }
            else
            {
                fhirImplementationGuide.Status = PublicationStatus.Draft;
            }

            if (summaryType == null || summaryType == SummaryType.Data)
            {
                // Package
                FhirImplementationGuide.PackageComponent package = new FhirImplementationGuide.PackageComponent();
                package.Name = "Profiles in this Implementation Guide";
                fhirImplementationGuide.Package.Add(package);

                // Page: Create a page for the implementation guide. This is required by the fhir ig publisher
                fhirImplementationGuide.Page        = new FhirImplementationGuide.PageComponent();
                fhirImplementationGuide.Page.Kind   = FhirImplementationGuide.GuidePageKind.Page;
                fhirImplementationGuide.Page.Title  = ig.GetDisplayName();
                fhirImplementationGuide.Page.Source = string.Format("{0}://{1}/IG/View/{2}", this.scheme, this.authority, ig.Id);

                // Add profiles to the implementation guide
                List <Template> templates        = ig.GetRecursiveTemplates(this.tdb, inferred: false);
                var             profileResources = (from t in templates.OrderBy(y => y.ImpliedTemplateId)
                                                    select new FhirImplementationGuide.ResourceComponent()
                {
                    Example = false,
                    Source = new ResourceReference()
                    {
                        Reference = string.Format("StructureDefinition/{0}", t.FhirId()),
                        Display = t.Name
                    }
                });
                package.Resource.AddRange(profileResources);

                if (includeVocabulary)
                {
                    // Add value sets to the implementation guide
                    var valueSetsIds = (from t in templates
                                        join tc in this.tdb.TemplateConstraints.AsNoTracking() on t.Id equals tc.TemplateId
                                        where tc.ValueSetId != null
                                        select tc.ValueSetId)
                                       .Distinct()
                                       .ToList();
                    var valueSets = (from vs in this.tdb.ValueSets
                                     join vsi in valueSetsIds on vs.Id equals vsi
                                     select vs).ToList();
                    var valueSetResources = (from vs in valueSets
                                             where vs.GetIdentifier() != null && !vs.GetIdentifier().StartsWith("http://hl7.org/fhir/ValueSet/")    // Ignore value sets in the base spec
                                             select new FhirImplementationGuide.ResourceComponent()
                    {
                        Example = false,
                        Source = new ResourceReference()
                        {
                            Reference = string.Format("ValueSet/{0}", vs.GetFhirId()),
                            Display = vs.Name
                        }
                    });
                    package.Resource.AddRange(valueSetResources);
                }

                // Add each of the individual FHIR resources added as files to the IG
                foreach (var file in ig.Files)
                {
                    var      fileData = file.GetLatestData();
                    Resource resource = null;

                    try
                    {
                        string fileContent = System.Text.Encoding.UTF8.GetString(fileData.Data);

                        if (file.MimeType == "application/xml" || file.MimeType == "text/xml")
                        {
                            resource = fhirXmlParser.Parse <Resource>(fileContent);
                        }
                        else if (file.MimeType == "application/json")
                        {
                            resource = fhirJsonParser.Parse <Resource>(fileContent);
                        }
                    }
                    catch
                    {
                    }

                    if (resource == null || string.IsNullOrEmpty(resource.Id))
                    {
                        continue;
                    }

                    var packageFile = new FhirImplementationGuide.ResourceComponent()
                    {
                        Example = false,
                        Source  = new ResourceReference()
                        {
                            Reference = string.Format("{0}/{1}", resource.ResourceType, resource.Id),
                            Display   = GetResourceName(resource, file.FileName)
                        }
                    };

                    package.Resource.Add(packageFile);
                }

                // Add each of the samples generated for the template/profile
                var templateExamples = (from t in templates
                                        join ts in this.tdb.TemplateSamples on t.Id equals ts.TemplateId
                                        select new { Template = t, Sample = ts });

                foreach (var templateExample in templateExamples)
                {
                    Resource resource = null;

                    try
                    {
                        resource = fhirXmlParser.Parse <Resource>(templateExample.Sample.XmlSample);
                    }
                    catch
                    {
                    }

                    try
                    {
                        if (resource == null)
                        {
                            resource = fhirJsonParser.Parse <Resource>(templateExample.Sample.XmlSample);
                        }
                    }
                    catch
                    {
                    }

                    if (resource == null || string.IsNullOrEmpty(resource.Id))
                    {
                        continue;
                    }

                    var packageExample = new FhirImplementationGuide.ResourceComponent()
                    {
                        Example = true,
                        Source  = new ResourceReference()
                        {
                            Reference = string.Format("{0}/{1}", resource.ResourceType, resource.Id),
                            Display   = GetResourceName(resource, templateExample.Sample.Name)
                        },
                        ExampleFor = new ResourceReference()
                        {
                            Reference = string.Format("StructureDefinition/{0}", templateExample.Template.Bookmark),
                            Display   = templateExample.Template.Name
                        }
                    };

                    package.Resource.Add(packageExample);
                }
            }

            return(fhirImplementationGuide);
        }
示例#20
0
 /// <summary>
 /// Search for Resources across the whole server that match the given criteria
 /// </summary>
 /// <param name="criteria">Optional. The search parameters to filter the resources on. Each
 /// given string is a combined key/value pair (separated by '=')</param>
 /// <param name="includes">Optional. A list of include paths</param>
 /// <param name="pageSize">Optional. Asks server to limit the number of entries per page returned</param>
 /// <param name="summary">Optional. Whether to include only return a summary of the resources in the Bundle</param>
 /// <param name="revIncludes">Optional. A list of reverse include paths</param>
 /// <returns>A Bundle with all resources found by the search, or an empty Bundle if none were found.</returns>
 /// <remarks>All parameters are optional, leaving all parameters empty will return an unfiltered list
 /// of all resources of the given Resource type</remarks>
 public Bundle WholeSystemSearchUsingPost(string[] criteria   = null, string[] includes    = null, int?pageSize = null,
                                          SummaryType?summary = null, string[] revIncludes = null)
 {
     return(WholeSystemSearchUsingPostAsync(criteria, includes, pageSize, summary, revIncludes).WaitResult());
 }
示例#21
0
 /// <summary>
 /// Search for Resources across the whol server that match the given criteria
 /// </summary>
 /// <param name="criteria">Optional. The search parameters to filter the resources on. Each
 /// given string is a combined key/value pair (separated by '=')</param>
 /// <param name="includes">Optional. A list of include paths</param>
 /// <param name="pageSize">Optional. Asks server to limit the number of entries per page returned</param>
 /// <param name="summary">Optional. Whether to include only return a summary of the resources in the Bundle</param>
 /// <returns>A Bundle with all resources found by the search, or an empty Bundle if none were found.</returns>
 /// <remarks>All parameters are optional, leaving all parameters empty will return an unfiltered list
 /// of all resources of the given Resource type</remarks>
 public Bundle WholeSystemSearch(string[] criteria = null, string[] includes = null, int?pageSize = null, SummaryType?summary = null)
 {
     return(Search(toQuery(criteria, includes, pageSize, summary)));
 }
示例#22
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);
        }