Exemplo n.º 1
0
        private void FillValues(TerminologyOperation termOp, string version, string code, string filter, string identifier, int offsetNo, int countNo, string useContext)
        {
            //if(!string.IsNullOrEmpty(code) && char.IsLetter(code[0]))
            if (!string.IsNullOrEmpty(code) && code.StartsWith("LL"))
            {
                throw new Exception(UNSUPPORTED_ANSWER_LIST);
            }

            // determine if filter contains a LOINC property-related query
            string loincProperty = string.Empty;
            string loincValue    = string.Empty;

            // Look for property filter & place code in filter e.g. SYSTEM=Arterial System
            int component_Filter  = identifier.IndexOf("/COMPONENT=");
            int property_Filter   = identifier.IndexOf("/PROPERTY=");
            int time_aspct_Filter = identifier.IndexOf("/TIME_ASPCT=");
            int system_Filter     = identifier.IndexOf("/SYSTEM=");
            int scale_typ_Filter  = identifier.IndexOf("/SCALE_TYP=");
            int method_typ_Filter = identifier.IndexOf("/METHOD_TYP=");

            //int consumer_name_Filter = identifier.IndexOf("/CONSUMER_NAME=");
            int class_Filter     = identifier.IndexOf("/CLASS=");
            int classType_Filter = identifier.IndexOf("/CLASSTYPE=");
            int order_obs_Filter = identifier.IndexOf("/ORDER_OBS=");

            if (component_Filter > 0)
            {
                loincProperty = "COMPONENT";
                loincValue    = identifier.Substring(component_Filter + 11);
            }
            else if (property_Filter > 0)
            {
                loincProperty = "PROPERTY";
                loincValue    = identifier.Substring(property_Filter + 10);
            }
            else if (time_aspct_Filter > 0)
            {
                loincProperty = "TIME_ASPCT";
                loincValue    = identifier.Substring(time_aspct_Filter + 12);
            }
            else if (system_Filter > 0)
            {
                loincProperty = "SYSTEM";
                loincValue    = identifier.Substring(system_Filter + 8);
            }
            else if (scale_typ_Filter > 0)
            {
                loincProperty = "SCALE_TYP";
                loincValue    = identifier.Substring(scale_typ_Filter + 11);
            }
            else if (method_typ_Filter > 0)
            {
                loincProperty = "METHOD_TYP";
                loincValue    = identifier.Substring(method_typ_Filter + 12);
            }
            else if (order_obs_Filter > 0)
            {
                loincProperty = "ORDER_OBS";
                loincValue    = identifier.Substring(order_obs_Filter + 11);
            }
            else if (classType_Filter > 0)
            {
                loincProperty = "CLASSTYPE";
                loincValue    = identifier.Substring(classType_Filter + 11);
            }
            else if (class_Filter > 0)
            {
                loincProperty = "CLASS";
                loincValue    = identifier.Substring(class_Filter + 7);
            }
            //else if (consumer_name_Filter > 0)
            //{
            //    loincProperty = "CONSUMER_NAME";
            //    loincValue = identifier.Substring(consumer_name_Filter + 15);
            //}

            string description = "All LOINC Codes Filtered By: " + filter;
            string title       = "LOINC";
            string idSuffix    = filter.Replace(" ", "_");

            if (!string.IsNullOrEmpty(loincProperty) && !string.IsNullOrEmpty(loincValue))
            {
                description = "LOINC codes where " + loincProperty + " = " + loincValue;
                title       = "LOINC Codes: " + loincProperty + "=" + loincValue;
                idSuffix    = loincValue.Replace(" ", "_");
            }

            this.valueSet   = new ValueSet();
            this.codeSystem = new CodeSystem();

            this.valueSet.Id   = "fhir_loinc_vs_" + idSuffix;
            this.codeSystem.Id = "LOINC";

            this.codeSystem.CaseSensitive    = true;
            this.codeSystem.Content          = CodeSystem.CodeSystemContentMode.NotPresent;
            this.codeSystem.Experimental     = false;
            this.codeSystem.Compositional    = false;
            this.codeSystem.VersionNeeded    = false;
            this.codeSystem.HierarchyMeaning = CodeSystem.CodeSystemHierarchyMeaning.PartOf;

            // Code System filters

            List <FilterOperator?> fops = new List <FilterOperator?>();

            fops.Add(FilterOperator.Equal);
            this.codeSystem.Filter.Add(new CodeSystem.FilterComponent {
                Code = "property", Description = "Allows the selection of a set of LOINC codes with a common property value.", Value = "A LOINC Code", Operator = fops.AsEnumerable()
            });


            this.valueSet.Url   = ServerCapability.TERMINZ_CANONICAL + "/ValueSet/loinc/" + idSuffix;
            this.codeSystem.Url = FhirLoinc.URI;

            this.codeSystem.ValueSet = "http://loinc.org/vs";

            this.valueSet.Title   = title;
            this.codeSystem.Title = FhirLoinc.TITLE;

            this.valueSet.Name   = this.valueSet.Id;
            this.codeSystem.Name = this.codeSystem.Id;


            this.valueSet.Description   = new Markdown(description);
            this.codeSystem.Description = new Markdown(FhirLoinc.DESCRIPTION);

            this.valueSet.Version   = FhirLoinc.CURRENT_VERSION;
            this.codeSystem.Version = FhirLoinc.CURRENT_VERSION;

            this.valueSet.Experimental = true;

            this.valueSet.Status   = PublicationStatus.Active;
            this.codeSystem.Status = PublicationStatus.Active;

            this.valueSet.Date   = Hl7.Fhir.Model.Date.Today().Value;
            this.codeSystem.Date = Hl7.Fhir.Model.Date.Today().Value;

            this.valueSet.Publisher   = "Patients First Ltd";
            this.codeSystem.Publisher = "Regenstrief Institute, Inc.";

            this.valueSet.Copyright   = new Markdown("This content LOINC is copyright © 1995 Regenstrief Institute, Inc. and the LOINC Committee, and available at no cost under the license at http://loinc.org/terms-of-use");
            this.codeSystem.Copyright = this.valueSet.Copyright;

            ContactPoint cp = new ContactPoint {
                System = ContactPoint.ContactPointSystem.Email, Value = "*****@*****.**"
            };
            ContactDetail cd = new ContactDetail();

            cd.Telecom.Add(cp);
            this.valueSet.Contact.Add(cd);
            this.codeSystem.Contact.Add(cd);

            ValueSet.ConceptSetComponent cs = new ValueSet.ConceptSetComponent();
            ValueSet.ExpansionComponent  es = new ValueSet.ExpansionComponent();

            cs.System  = this.codeSystem.Url;
            cs.Version = this.codeSystem.Version;

            string codeCode       = string.Empty;
            string codeDisplay    = string.Empty;
            string codeDefinition = string.Empty;

            if ((string.IsNullOrEmpty(version) || version == cs.Version) && termOp != TerminologyOperation.define_cs)
            {
                List <Coding> codeVals = new List <Coding>();

                if (termOp != TerminologyOperation.define_vs)
                {
                    if (!string.IsNullOrEmpty(loincProperty) && !string.IsNullOrEmpty(loincValue))
                    {
                        codeVals = LoincSearch.GetConceptsByProperty(loincProperty, loincValue);
                    }
                    else if (!string.IsNullOrEmpty(code))
                    {
                        // returning Parameters Resource with False appears to be preferred to OperationOutcome failure
                        //if (!Utilities.IsDigitsOnly(code))
                        //{
                        //    throw new Exception(TerminologyValueSet.INVALID_CODE);
                        //}
                        if (termOp == TerminologyOperation.find_matches)
                        {
                            codeVals = LoincSearch.GetPropertiesByCode(code, "ALL");
                        }
                        else if (code.StartsWith("LP"))
                        {
                            codeVals = LoincSearch.GetConceptByPartCode(code);
                        }
                        else if (code.StartsWith("LA"))
                        {
                            codeVals = LoincSearch.GetConceptByAnswerStringId(code);
                        }
                        else
                        {
                            codeVals = LoincSearch.GetConceptByCode(code);
                        }
                    }
                    else if (!string.IsNullOrEmpty(filter))
                    {
                        if (filter.Length < 3)
                        {
                            throw new Exception(TerminologyValueSet.INVALID_FILTER);
                        }
                        codeVals = LoincSearch.GetConceptsByTerm(filter);
                    }
                    else // can't pass LOINC in its entirety!
                    {
                        throw new Exception(TerminologyValueSet.MISSING_FILTER);
                    }

                    if (codeVals.Count > 9999)
                    {
                        throw new Exception(TerminologyValueSet.MAX_VALUES_EXCEEDED);
                    }
                }

                // filtering performed at DB Layer, so add all returned concepts
                foreach (Coding codeVal in codeVals)
                {
                    if (useContext == "CONSUMER_NAME" && !string.IsNullOrEmpty(codeVal.System))
                    {
                        codeVal.Display = codeVal.Version;
                    }
                    cs.Concept.Add(new ValueSet.ConceptReferenceComponent {
                        Code = codeVal.Code, Display = codeVal.Display
                    });
                    es.Contains.Add(new ValueSet.ContainsComponent {
                        Code = codeVal.Code, Display = codeVal.Display, System = cs.System
                    });
                    this.codeSystem.Concept.Add(new CodeSystem.ConceptDefinitionComponent {
                        Code = codeVal.Code, Display = codeVal.Display
                    });
                }

                if (termOp == TerminologyOperation.expand || termOp == TerminologyOperation.validate_code)
                {
                    this.valueSet = TerminologyValueSet.AddExpansion(this.valueSet, es, offsetNo, countNo);
                }
                else if (termOp == TerminologyOperation.define_vs)
                {
                    this.valueSet.Compose = new ValueSet.ComposeComponent();
                    this.valueSet.Compose.Include.Add(cs);
                }
            }
        }
        private static Resource LookupOperation(string systemURL, NameValueCollection queryParam)
        {
            CodeSystem codeSys = GetCodeSystem(TerminologyOperation.lookup, systemURL, queryParam);

            if (codeSys.Concept.Count < 1)
            {
                throw new Exception(INVALID_CODE);
            }

            string codeVal = Utilities.GetQueryValue("code", queryParam);
            //string versionVal = Utilities.GetQueryValue("version", queryParam);
            string propertyVal = Utilities.GetQueryValue("property", queryParam);
            string languageVal = Utilities.GetQueryValue("displayLanguage", queryParam);

            if (!string.IsNullOrEmpty(languageVal) && languageVal != "en-NZ")
            {
                throw new Exception(UNSUPPORTED_DISPLAY_LANGUAGE);
            }

            bool displayCode                = false;
            bool displaySystem              = false;
            bool displayVersion             = true;
            bool displayDisplay             = true;
            bool displayDefinition          = false;
            bool displayDesignation         = false;
            bool displayParents             = false;
            bool displayChildren            = false;
            bool displaySubstance           = false;
            bool displayInactive            = false;
            bool displayModuleId            = false;
            bool displaySufficientlyDefined = false;
            bool displayNf              = false;
            bool displayNfTerse         = false;
            bool displayAllAttributes   = false;
            bool displaySingleAttribute = false;
            bool displayTermType        = false;

            // standard properties...defined for all Code Systems

            /*
             * // The following properties are defined for all code systems:
             * // system, version, display, definition, designation, parent, child, and lang.X where X is a language code in a designation
             * // SCT properties
             * // inactive	boolean	Whether the code is active or not (defaults to false). This is derived from the active column in the Concept file of the RF2 Distribution (by inverting the value)
             * // sufficientlyDefined	boolean	True if the description logic definition of the concept includes sufficient conditions (i.e., if the concept is not primitive).
             * // moduleId	code	The SNOMED CT concept id of the module that the concept belongs to.
             * // normalForm	string	Generated Normal form expression for the provided code or expression, with terms
             * // normalFormTerse	string	Generated Normal form expression for the provided code or expression, conceptIds only
             * // In addition, any SNOMED CT relationships where the relationship type is subsumed by Attribute (246061005) automatically become properties. For example, laterality:
             * // Laterality	code	In this case, the URI (See the code system definition) is http://snomed.info/id/272741003, which can be used to unambiguously map to the underlying concept
             */

            if (!string.IsNullOrEmpty(propertyVal))
            {
                string pvl = propertyVal.ToLower();
                displayCode   = (pvl.Contains("code"));
                displaySystem = (pvl.Contains("system"));
                //displayVersion = (pvl.Contains("version")); // always return code system version
                //displayDisplay = true;  // default true - don't see much point in looking up the code and not displaying its description! (otherwise use validate-code)
                displayDefinition          = (pvl.Contains("definition"));
                displayDesignation         = (pvl.Contains("designation"));
                displayParents             = (pvl.Contains("parent"));
                displayChildren            = (pvl.Contains("child"));
                displaySubstance           = (pvl.Contains("substance"));
                displayTermType            = (pvl.Contains("termtype"));
                displayInactive            = (pvl.Contains("inactive"));
                displaySufficientlyDefined = (pvl.Contains("sufficientlydefined"));
                displayModuleId            = (pvl.Contains("moduleid"));
                displayNfTerse             = (pvl.Contains("normalformterse"));
                displayNf            = (pvl.Contains("normalform") && !displayNfTerse);
                displayAllAttributes = (pvl.Contains(FhirSnomed.SCT_ATTRIBUTE_CONCEPT));
                if (!displayAllAttributes)
                {
                    displaySingleAttribute = (pvl.Count(x => Char.IsDigit(x)) > 7);
                }
            }

            List <Coding> loincPropertyVals         = new List <Coding>();
            List <Coding> substanceCodeVals         = new List <Coding>();
            List <Coding> designationCodeVals       = new List <Coding>();
            List <Coding> childCodeVals             = new List <Coding>();
            List <Coding> parentCodeVals            = new List <Coding>();
            List <Coding> propertyCodeVals          = new List <Coding>();
            List <Coding> attributeCodeVals         = new List <Coding>();
            List <Coding> termTypeVals              = new List <Coding>();
            List <Coding> proximalPrimitiveCodeVals = new List <Coding>();

            // CodeSystem-specific actions

            if (systemURL == NzMt.URI)
            {
                string nzulmType = codeSys.Concept[0].Definition;
                string mp_id     = codeSys.Concept[0].ElementId;
                if (displaySubstance)
                {
                    substanceCodeVals = NzUlmSearch.GetConceptSubstanceDataByCode(mp_id, nzulmType);
                }
            }

            if (systemURL == FhirLoinc.URI)
            {
                if (!string.IsNullOrEmpty(propertyVal))
                {
                    loincPropertyVals = LoincSearch.GetPropertiesByCode(codeVal, propertyVal.ToUpper());
                }
            }

            if (systemURL == FhirRxNorm.URI)
            {
                if (displayTermType)
                {
                    termTypeVals = RxNormSearch.GetPropertiesByCode(codeVal);
                }
            }

            if (systemURL == FhirSnomed.URI)
            {
                displaySystem      = true;
                displayDesignation = true;
                displayInactive    = true;

                if (codeSys.Concept.Count > 0)
                {
                    if (displayDesignation)
                    {
                        designationCodeVals = SnomedCtSearch.GetConceptDesignationsByCode(codeVal);
                    }

                    if (displayInactive || displayModuleId || displaySufficientlyDefined)
                    {
                        propertyCodeVals = SnomedCtSearch.GetConceptPropertiesByCode(codeVal);
                    }

                    if (displayChildren)
                    {
                        childCodeVals = SnomedCtSearch.GetChildCodes(codeVal);
                    }

                    if (displayParents)
                    {
                        parentCodeVals = SnomedCtSearch.GetParentCodes(codeVal);
                    }

                    if (displayAllAttributes || displaySingleAttribute)
                    {
                        List <Coding> acv = SnomedCtSearch.GetAttributes(codeVal);
                        if (displayAllAttributes)
                        {
                            attributeCodeVals = acv;
                        }
                        else
                        {
                            foreach (Coding cv in acv)
                            {
                                if (propertyVal.Contains(cv.Code))
                                {
                                    attributeCodeVals.Add(cv);
                                }
                            }
                        }
                    }
                }
            }

            // build return parameters resource using default & requested properties
            Parameters param = new Parameters();

            if (codeSys.Concept != null)
            {
                param.Add("name", codeSys.NameElement);

                foreach (CodeSystem.ConceptDefinitionComponent comp in codeSys.Concept)
                {
                    if (displaySystem)
                    {
                        param.Add("system", codeSys.UrlElement);
                    }
                    if (displayVersion)
                    {
                        param.Add("version", codeSys.VersionElement);
                    }
                    if (displayCode)
                    {
                        param.Add("code", comp.CodeElement);
                    }
                    if (displayDisplay)
                    {
                        param.Add("display", comp.DisplayElement);
                    }
                }

                foreach (Coding prop in loincPropertyVals)
                {
                    // return all of them
                    List <Tuple <string, Base> > tuples = new List <Tuple <string, Base> >
                    {
                        new Tuple <string, Base>("code", new FhirString(prop.Code)),
                        new Tuple <string, Base>("value", new FhirString(prop.Display))
                    };
                    param.Add("property", tuples);
                }

                foreach (Coding tty in termTypeVals)
                {
                    List <Tuple <string, Base> > tuples = new List <Tuple <string, Base> >
                    {
                        //new Tuple<string, Base>("code", new FhirString(tty.Version)),
                        //new Tuple<string, Base>("value", new FhirString(FhirRxNorm.GetTermType(tty.Version))),
                        //new Tuple<string, Base>("description", new FhirString(tty.Display))
                        new Tuple <string, Base>("use", new Coding {
                            Display = FhirRxNorm.GetTermType(tty.Version), System = FhirRxNorm.URI, Code = tty.Version
                        }),
                        new Tuple <string, Base>("value", new FhirString(tty.Display))
                    };
                    param.Add("termType", tuples);
                }

                foreach (Coding desig in designationCodeVals)
                {
                    List <Tuple <string, Base> > tuples = new List <Tuple <string, Base> >
                    {
                        new Tuple <string, Base>("use", new Coding {
                            Display = desig.System, System = FhirSnomed.URI, Code = FhirSnomed.GetDesignationTypeId(desig.System)
                        }),
                        new Tuple <string, Base>("value", new FhirString(desig.Display))
                    };
                    param.Add("designation", tuples);
                }

                foreach (Coding prop in propertyCodeVals)
                {
                    if ((prop.Code == "inactive" && displayInactive) ||
                        (prop.Code == "sufficientlyDefined" && displaySufficientlyDefined) ||
                        (prop.Code == "moduleId" && displayModuleId))
                    {
                        List <Tuple <string, Base> > tuples = new List <Tuple <string, Base> >
                        {
                            new Tuple <string, Base>("code", new FhirString(prop.Code)),
                            new Tuple <string, Base>("value", new FhirString(prop.Display))
                        };
                        param.Add("property", tuples);
                    }
                }

                if (displayNf || displayNfTerse)
                {
                    string nf = FhirSnomed.GetNormalFormDisplay(codeVal, displayNf);
                    List <Tuple <string, Base> > tuples = new List <Tuple <string, Base> >
                    {
                        new Tuple <string, Base>("code", new FhirString(displayNf ? "normalForm" : "normalFormTerse")),
                        new Tuple <string, Base>("value", new FhirString(nf))
                    };
                    param.Add("property", tuples);
                }

                foreach (Coding subst in substanceCodeVals)
                {
                    List <Tuple <string, Base> > tuples = new List <Tuple <string, Base> >
                    {
                        new Tuple <string, Base>("use", new Coding {
                            Display = subst.System
                        })
                    };
                    if (!string.IsNullOrEmpty(subst.Code))
                    {
                        tuples.Add(new Tuple <string, Base>("code", new FhirString(subst.Code)));
                    }
                    tuples.Add(new Tuple <string, Base>("value", new FhirString(subst.Display)));
                    param.Add("substance", tuples);
                }

                foreach (Coding parent in parentCodeVals)
                {
                    List <Tuple <string, Base> > tuples = new List <Tuple <string, Base> >
                    {
                        new Tuple <string, Base>("code", new FhirString("Parent")),
                        new Tuple <string, Base>("value", new FhirString(parent.Code)),
                        new Tuple <string, Base>("description", new FhirString(parent.Display))
                    };
                    param.Add("property", tuples);
                }

                foreach (Coding child in childCodeVals)
                {
                    List <Tuple <string, Base> > tuples = new List <Tuple <string, Base> >
                    {
                        new Tuple <string, Base>("code", new FhirString("Child")),
                        new Tuple <string, Base>("value", new FhirString(child.Code)),
                        new Tuple <string, Base>("description", new FhirString(child.Display))
                    };
                    param.Add("property", tuples);
                }

                foreach (Coding attrib in attributeCodeVals)
                {
                    List <Tuple <string, Base> > tuples = new List <Tuple <string, Base> >
                    {
                        new Tuple <string, Base>("code", new Code {
                            Value = attrib.Code
                        }),
                        new Tuple <string, Base>("valueCode", new Code {
                            Value = attrib.Display
                        })
                    };
                    param.Add("property", tuples);
                }
            }

            return(param);
        }
Exemplo n.º 3
0
        private void FillValues(TerminologyOperation termOp, string version, string code, string filter, int offsetNo, int countNo)
        {
            this.valueSet     = new ValueSet();
            this.valueSet.Id  = "intensional-case-1";
            this.valueSet.Url = "http://www.healthintersections.com.au/fhir/ValueSet/intensional-case-1";
            this.valueSet.Identifier.Add(new Identifier {
                Value = this.valueSet.Id
            });
            this.valueSet.Name         = this.valueSet.Id;
            this.valueSet.Title        = "Terminology Services Test: Intensional case #1";
            this.valueSet.Description  = new Markdown("All loinc codes for system = Arterial system");
            this.valueSet.Version      = "R4";
            this.valueSet.Status       = PublicationStatus.Active;
            this.valueSet.Experimental = true;
            this.valueSet.Date         = Hl7.Fhir.Model.Date.Today().Value;
            this.valueSet.Publisher    = "Grahame Grieve";
            this.valueSet.Copyright    = new Markdown("This content LOINC is copyright © 1995 Regenstrief Institute, Inc. and the LOINC Committee, and available at no cost under the license at http://loinc.org/terms-of-use");

            ContactPoint cp = new ContactPoint {
                System = ContactPoint.ContactPointSystem.Email, Value = "*****@*****.**"
            };
            ContactDetail cd = new ContactDetail();

            cd.Telecom.Add(cp);
            this.valueSet.Contact.Add(cd);

            ValueSet.ConceptSetComponent cs = new ValueSet.ConceptSetComponent();
            cs.System  = FhirLoinc.URI;
            cs.Version = FhirLoinc.CURRENT_VERSION;
            cs.Filter.Add(new ValueSet.FilterComponent {
                Property = "SYSTEM", Op = FilterOperator.Equal, Value = "Arterial System"
            });

            string codeCode       = string.Empty;
            string codeDisplay    = string.Empty;
            string codeDefinition = string.Empty;

            if (string.IsNullOrEmpty(version) || version == cs.Version)
            {
                if (termOp == TerminologyOperation.expand || termOp == TerminologyOperation.validate_code)
                {
                    List <Coding> codeVals = new List <Coding>();
                    codeVals = LoincSearch.GetConceptsByProperty(cs.Filter[0].Property, cs.Filter[0].Value);
                    ValueSet.ExpansionComponent es = new ValueSet.ExpansionComponent();
                    foreach (Coding codeVal in codeVals)
                    {
                        if (TerminologyValueSet.MatchValue(codeVal.Code, codeVal.Display, code, filter))
                        {
                            es.Contains.Add(new ValueSet.ContainsComponent {
                                Code = codeVal.Code, Display = codeVal.Display, System = cs.System
                            });
                        }
                    }
                    this.valueSet = TerminologyValueSet.AddExpansion(this.valueSet, es, offsetNo, countNo);
                }
                else
                {
                    this.valueSet.Compose = new ValueSet.ComposeComponent();
                    this.valueSet.Compose.Include.Add(cs);
                }
            }
        }