Example #1
0
        /// <summary>Initializes a new instance of the <see cref="FhirCodeSystem"/> class.</summary>
        /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception>
        /// <param name="name">          The name.</param>
        /// <param name="id">            The identifier.</param>
        /// <param name="version">       The version.</param>
        /// <param name="title">         The title.</param>
        /// <param name="url">           The URL.</param>
        /// <param name="standardStatus">The standard status.</param>
        /// <param name="description">   The description.</param>
        /// <param name="content">       The content.</param>
        /// <param name="rootConcept">   The root concept.</param>
        /// <param name="conceptLookup"> The concept lookup.</param>
        public FhirCodeSystem(
            string name,
            string id,
            string version,
            string title,
            string url,
            string standardStatus,
            string description,
            string content,
            FhirConceptTreeNode rootConcept,
            Dictionary <string, FhirConceptTreeNode> conceptLookup)
        {
            if (url == null)
            {
                throw new ArgumentNullException(nameof(url));
            }

            Name           = name;
            Id             = id;
            Version        = version;
            Title          = title;
            URL            = url;
            StandardStatus = standardStatus;
            Description    = description;
            Content        = content;
            _rootConcept   = rootConcept;
            _conceptLookup = conceptLookup;
        }
Example #2
0
        /// <summary>Adds a node.</summary>
        /// <param name="concept">The concept.</param>
        /// <returns>A FhirConceptTreeNode.</returns>
        public FhirConceptTreeNode AddChild(FhirConcept concept)
        {
            if (concept == null)
            {
                return(null);
            }

            if (_children.ContainsKey(concept.Code))
            {
                return(_children[concept.Code]);
            }

            FhirConceptTreeNode node = new FhirConceptTreeNode(concept, this);

            _children.Add(concept.Code, node);

            return(node);
        }
Example #3
0
 /// <summary>Initializes a new instance of the <see cref="FhirConceptTreeNode"/> class.</summary>
 /// <param name="concept">The concept.</param>
 /// <param name="parent"> The parent.</param>
 public FhirConceptTreeNode(FhirConcept concept, FhirConceptTreeNode parent)
 {
     _concept  = concept;
     _children = new Dictionary <string, FhirConceptTreeNode>();
     _parent   = parent;
 }
Example #4
0
        /// <summary>Adds from node.</summary>
        /// <param name="values">          [in,out] The values.</param>
        /// <param name="node">            The node.</param>
        /// <param name="includeSelf">     True to include, false to exclude the self.</param>
        /// <param name="includeChildren"> True to include, false to exclude the children.</param>
        /// <param name="includeParents">  True to include, false to exclude the parents.</param>
        /// <param name="exclusionKey">    The exclusion key.</param>
        /// <param name="regex">           The RegEx.</param>
        /// <param name="inclusionSet">    Set the inclusion belongs to.</param>
        /// <param name="exclusionSet">    Set the exclusion belongs to.</param>
        /// <param name="maxRecursions">   (Optional) The maximum recursions (-1 for no limit).</param>
        /// <param name="filterProperties">(Optional) The include properties.</param>
        private static void AddFromNode(
            ref Dictionary <string, FhirConcept> values,
            FhirConceptTreeNode node,
            bool includeSelf,
            bool includeChildren,
            bool includeParents,
            string exclusionKey,
            Regex regex,
            HashSet <string> inclusionSet,
            HashSet <string> exclusionSet,
            int maxRecursions = -1,
            List <KeyValuePair <string, string> > filterProperties = null)
        {
            if ((!string.IsNullOrEmpty(exclusionKey)) &&
                (node.Concept != null) &&
                (node.Concept.Code == exclusionKey))
            {
                return;
            }

            if (includeSelf &&
                (node.Concept != null) &&
                (!values.ContainsKey(node.Concept.Code)) &&
                ((regex == null) || regex.IsMatch(node.Concept.Code)) &&
                ((inclusionSet == null) || inclusionSet.Contains(node.Concept.Code)) &&
                ((exclusionSet == null) || (!exclusionSet.Contains(node.Concept.Code))))
            {
                string key = node.Concept.Key();

                if (!values.ContainsKey(key))
                {
                    if ((filterProperties != null) && (filterProperties.Count > 0))
                    {
                        if (node.Concept.MatchesProperties(filterProperties))
                        {
                            values.Add(key, node.Concept);
                        }
                    }
                    else
                    {
                        values.Add(key, node.Concept);
                    }
                }
            }

            if (includeChildren &&
                (node.Children != null) &&
                (maxRecursions != 0))
            {
                if (maxRecursions > 0)
                {
                    maxRecursions--;
                }

                foreach (FhirConceptTreeNode child in node.Children.Values)
                {
                    AddFromNode(
                        ref values,
                        child,
                        true,
                        true,
                        false,
                        exclusionKey,
                        regex,
                        inclusionSet,
                        exclusionSet,
                        maxRecursions,
                        filterProperties);
                }
            }

            if (includeParents &&
                (node.Parent != null) &&
                (maxRecursions != 0))
            {
                if (maxRecursions > 0)
                {
                    maxRecursions--;
                }

                AddFromNode(
                    ref values,
                    node.Parent,
                    true,
                    false,
                    true,
                    exclusionKey,
                    regex,
                    inclusionSet,
                    exclusionSet,
                    maxRecursions,
                    filterProperties);
            }
        }
Example #5
0
        /// <summary>Adds a filtered concepts.</summary>
        /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception>
        /// <param name="values">    [in,out] The values.</param>
        /// <param name="codeSystem">The code system.</param>
        /// <param name="filters">   Specifies the filters.</param>
        /// <param name="include">   True to include, false to exclude.</param>
        /// <param name="exclude">   True to exclude, false to include.</param>
        private static void ApplyFilteredConcepts(
            ref Dictionary <string, FhirConcept> values,
            FhirCodeSystem codeSystem,
            List <FhirValueSetFilter> filters,
            bool include,
            bool exclude)
        {
            if (codeSystem == null)
            {
                throw new ArgumentNullException(nameof(codeSystem));
            }

            if ((filters == null) || (filters.Count == 0))
            {
                throw new ArgumentNullException(nameof(filters));
            }

            if (include && exclude)
            {
#pragma warning disable CA1303 // Do not pass literals as localized parameters
                throw new Exception("Cannot include and exclude the same filters!");
#pragma warning restore CA1303 // Do not pass literals as localized parameters
            }

            if ((!include) && (!exclude))
            {
#pragma warning disable CA1303 // Do not pass literals as localized parameters
                throw new Exception("Must either include or exclude for filters!");
#pragma warning restore CA1303 // Do not pass literals as localized parameters
            }

            string           startingCode    = string.Empty;
            bool             includeSelf     = false;
            bool             includeChildren = false;
            bool             includeParents  = false;
            string           exclusionKey    = string.Empty;
            Regex            regex           = null;
            HashSet <string> inclusionSet    = null;
            HashSet <string> exclusionSet    = null;
            int maxRecusrions = -1;
            List <KeyValuePair <string, string> > filterProperties = new List <KeyValuePair <string, string> >();

            foreach (FhirValueSetFilter filter in filters)
            {
                string filterKey = $"{filter.Property}:{filter.Operation}";

                switch (filterKey)
                {
                case "concept:=":
                    startingCode    = filter.Value;
                    includeSelf     = true;
                    includeChildren = false;
                    includeParents  = false;

                    break;

                case "concept:is-a":
                    startingCode    = filter.Value;
                    includeSelf     = true;
                    includeChildren = true;
                    includeParents  = false;

                    break;

                case "concept:descendent-of":
                    startingCode    = filter.Value;
                    includeSelf     = false;
                    includeChildren = true;
                    includeParents  = false;

                    break;

                case "concept:is-not-a":
                    exclusionKey = filter.Value;
                    break;

                case "concept:regex":
                    regex = new Regex(filter.Value);
                    break;

                case "concept:in":
                    inclusionSet = new HashSet <string>();

                    string[] inculsions = filter.Value.Split(',');

                    foreach (string value in inculsions)
                    {
                        inclusionSet.Add(value);
                    }

                    break;

                case "concept:not-in":
                    exclusionSet = new HashSet <string>();

                    string[] exclusions = filter.Value.Split(',');

                    foreach (string value in exclusions)
                    {
                        exclusionSet.Add(value);
                    }

                    break;

                case "concept:generalizes":
                    startingCode    = filter.Value;
                    includeSelf     = true;
                    includeChildren = false;
                    includeParents  = true;

                    break;

                case "parent:=":
                    startingCode    = filter.Value;
                    includeSelf     = false;
                    includeChildren = true;
                    includeParents  = false;
                    maxRecusrions   = 1;
                    break;

                case "child:=":
                    startingCode    = filter.Value;
                    includeSelf     = false;
                    includeChildren = false;
                    includeParents  = true;
                    maxRecusrions   = 1;
                    break;

                // ignore these
                case "acme-plasma:=":
                    return;

                case "concept:exists":
                default:
                    if (filter.Operation == "=")
                    {
                        filterProperties.Add(new KeyValuePair <string, string>(filter.Property, filter.Value));

                        includeSelf     = true;
                        includeChildren = true;
                        includeParents  = false;

                        continue;
                    }

                    throw new NotImplementedException($"Unhandled filter: {filterKey}");
                }
            }

            FhirConceptTreeNode startingNode = codeSystem.RootConcept;

            if ((!string.IsNullOrEmpty(startingCode)) &&
                codeSystem.ContainsConcept(startingCode))
            {
                startingNode = codeSystem[startingCode];
            }

            if (include)
            {
                AddFromNode(
                    ref values,
                    startingNode,
                    includeSelf,
                    includeChildren,
                    includeParents,
                    exclusionKey,
                    regex,
                    inclusionSet,
                    exclusionSet,
                    maxRecusrions,
                    filterProperties);
            }

            if (exclude)
            {
                RemoveFromNode(
                    ref values,
                    startingNode,
                    includeSelf,
                    includeChildren,
                    includeParents,
                    exclusionKey,
                    regex,
                    inclusionSet,
                    exclusionSet,
                    maxRecusrions,
                    filterProperties);
            }
        }
        /// <summary>Removes from node.</summary>
        /// <param name="values">         [in,out] The values.</param>
        /// <param name="node">           The node.</param>
        /// <param name="includeSelf">    True to include, false to exclude the self.</param>
        /// <param name="includeChildren">True to include, false to exclude the children.</param>
        /// <param name="includeParents"> True to include, false to exclude the parents.</param>
        /// <param name="exclusionKey">   The exclusion key.</param>
        /// <param name="regex">          The RegEx.</param>
        /// <param name="inclusionSet">   Set the inclusion belongs to.</param>
        /// <param name="exclusionSet">   Set the exclusion belongs to.</param>
        /// <param name="maxRecursions">  (Optional) The maximum recursions (-1 for no limit).</param>
        private static void RemoveFromNode(
            ref Dictionary <string, FhirConcept> values,
            FhirConceptTreeNode node,
            bool includeSelf,
            bool includeChildren,
            bool includeParents,
            string exclusionKey,
            Regex regex,
            HashSet <string> inclusionSet,
            HashSet <string> exclusionSet,
            int maxRecursions = -1)
        {
            if ((!string.IsNullOrEmpty(exclusionKey)) &&
                (node.Concept.Code == exclusionKey))
            {
                return;
            }

            if (includeSelf &&
                (!values.ContainsKey(node.Concept.Code)) &&
                ((regex == null) || regex.IsMatch(node.Concept.Code)) &&
                ((inclusionSet == null) || inclusionSet.Contains(node.Concept.Code)) &&
                ((exclusionSet == null) || (!exclusionSet.Contains(node.Concept.Code))))
            {
                if (values.ContainsKey(node.Concept.Code))
                {
                    values.Remove(node.Concept.Code);
                }
            }

            if (includeChildren &&
                (node.Children != null) &&
                (maxRecursions != 0))
            {
                if (maxRecursions > 0)
                {
                    maxRecursions--;
                }

                foreach (FhirConceptTreeNode child in node.Children.Values)
                {
                    RemoveFromNode(
                        ref values,
                        child,
                        true,
                        true,
                        false,
                        exclusionKey,
                        regex,
                        inclusionSet,
                        exclusionSet,
                        maxRecursions);
                }
            }

            if (includeParents &&
                (node.Parent != null) &&
                (maxRecursions != 0))
            {
                if (maxRecursions > 0)
                {
                    maxRecursions--;
                }

                RemoveFromNode(
                    ref values,
                    node.Parent,
                    true,
                    false,
                    true,
                    exclusionKey,
                    regex,
                    inclusionSet,
                    exclusionSet,
                    maxRecursions);
            }
        }