Beispiel #1
0
        public static void CheckExpression(ITypedElement inputNav, Hl7.FhirPath.Expressions.Expression expr, Action <string, bool, string> AppendResults, Action ResetResults)
        {
            ExpressionElementContext context = new ExpressionElementContext(inputNav.Name);

            if (inputNav is dstu2::Hl7.Fhir.ElementModel.IFhirValueProvider pn2)
            {
                if (pn2.FhirValue is f2.Questionnaire q)
                {
                    context._q2 = q;
                }
            }
            else if (inputNav is stu3::Hl7.Fhir.ElementModel.IFhirValueProvider pn3)
            {
                if (pn3.FhirValue is f3.Questionnaire q)
                {
                    context._q3 = q;
                }
            }
            else if (inputNav is r4::Hl7.Fhir.ElementModel.IFhirValueProvider pn4)
            {
                if (pn4.FhirValue is f4.Questionnaire q)
                {
                    context._q4 = q;
                }
            }
            ResetResults();
            CheckExpression(expr, "", context, AppendResults);
        }
Beispiel #2
0
        public ExpressionElementContext Child(string propertyName)
        {
            // Special case for the top level node
            if (propertyName == _typeName)
            {
                return(this);
            }

            if (!HasProperty(propertyName, out var dstu2, out var stu3, out var r4))
            {
                return(null);
            }

            var newContext = new ExpressionElementContext();

            if (r4?.Any() == true)
            {
                foreach (var item in r4)
                {
                    try
                    {
                        if (item.Choice == r4::Hl7.Fhir.Introspection.ChoiceType.DatatypeChoice)
                        {
                            if (item.Name != propertyName && item.MatchesSuffixedName(propertyName))
                            {
                                string ExpectedType = propertyName.Substring(item.Name.Length);
                                if (Enum.TryParse <f4.FHIRAllTypes>(ExpectedType, out var result))
                                {
                                    if (f4.ModelInfo.IsDataType(result) || f4.ModelInfo.IsPrimitive(result))
                                    {
                                        // may need to recheck that a typename of value23 won't work here
                                        string name = f4.ModelInfo.FhirTypeToFhirTypeName(result);
                                        var    t    = f4.ModelInfo.GetTypeForFhirType(name);
                                        newContext._cm4.Add(r4::Hl7.Fhir.Introspection.ClassMapping.Create(t));
                                    }
                                }
                            }
                            else
                            {
                                // would be great to be able to filter through only the viable types
                                // but we don't have that, so just enumerate the available datatypes
                                foreach (f4.FHIRAllTypes ev in Enum.GetValues(typeof(f4.FHIRAllTypes)))
                                {
                                    if (f4.ModelInfo.IsDataType(ev) && !f4.ModelInfo.IsCoreSuperType(ev))
                                    {
                                        string name = f4.ModelInfo.FhirTypeToFhirTypeName(ev);
                                        var    t    = f4.ModelInfo.GetTypeForFhirType(name);
                                        newContext._cm4.Add(r4::Hl7.Fhir.Introspection.ClassMapping.Create(t));
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (item.ElementType != typeof(string)) // (only occurs for extension.url and elementdefinition.id)
                            {
                                newContext._cm4.Add(r4::Hl7.Fhir.Introspection.ClassMapping.Create(item.ElementType));
                            }
                        }
                    }
                    catch
                    {
                    }
                }
            }
            if (stu3?.Any() == true)
            {
                foreach (var item in stu3)
                {
                    try
                    {
                        if (item.Choice == stu3::Hl7.Fhir.Introspection.ChoiceType.DatatypeChoice)
                        {
                            if (item.Name != propertyName && item.MatchesSuffixedName(propertyName))
                            {
                                string ExpectedType = propertyName.Substring(item.Name.Length);
                                if (Enum.TryParse <f3.FHIRAllTypes>(ExpectedType, out var result))
                                {
                                    if (f3.ModelInfo.IsDataType(result) || f3.ModelInfo.IsPrimitive(result))
                                    {
                                        // may need to recheck that a typename of value23 won't work here
                                        string name = f3.ModelInfo.FhirTypeToFhirTypeName(result);
                                        var    t    = f3.ModelInfo.GetTypeForFhirType(name);
                                        newContext._cm3.Add(stu3::Hl7.Fhir.Introspection.ClassMapping.Create(t));
                                    }
                                }
                            }
                            else
                            {
                                // would be great to be able to filter through only the viable types
                                // but we don't have that, so just enumerate the available datatypes
                                foreach (f3.FHIRAllTypes ev in Enum.GetValues(typeof(f3.FHIRAllTypes)))
                                {
                                    if (f3.ModelInfo.IsDataType(ev) && !f3.ModelInfo.IsCoreSuperType(ev))
                                    {
                                        string name = f3.ModelInfo.FhirTypeToFhirTypeName(ev);
                                        var    t    = f3.ModelInfo.GetTypeForFhirType(name);
                                        newContext._cm3.Add(stu3::Hl7.Fhir.Introspection.ClassMapping.Create(t));
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (item.ImplementingType != typeof(string)) // (only occurs for extension.url and elementdefinition.id)
                            {
                                newContext._cm3.Add(stu3::Hl7.Fhir.Introspection.ClassMapping.Create(item.ImplementingType));
                            }
                        }
                    }
                    catch
                    {
                    }
                }
            }

            if (dstu2?.Any() == true)
            {
                foreach (var item in dstu2)
                {
                    try
                    {
                        if (item.Choice == dstu2::Hl7.Fhir.Introspection.ChoiceType.DatatypeChoice)
                        {
                            if (item.Name != propertyName && item.MatchesSuffixedName(propertyName))
                            {
                                string ExpectedType = propertyName.Substring(item.Name.Length);
                                if (Enum.TryParse <f2.FHIRDefinedType>(ExpectedType, out var result))
                                {
                                    if (f2.ModelInfo.IsDataType(result) || f2.ModelInfo.IsPrimitive(result))
                                    {
                                        // may need to recheck that a typename of value23 won't work here
                                        string name = f2.ModelInfo.FhirTypeToFhirTypeName(result);
                                        var    t    = f2.ModelInfo.GetTypeForFhirType(name);
                                        newContext._cm2.Add(dstu2::Hl7.Fhir.Introspection.ClassMapping.Create(t));
                                    }
                                }
                            }
                            else
                            {
                                // would be great to be able to filter through only the viable types
                                // but we don't have that, so just enumerate the available datatypes
                                foreach (f2.FHIRDefinedType ev in Enum.GetValues(typeof(f2.FHIRDefinedType)))
                                {
                                    if (f2.ModelInfo.IsDataType(ev) && !f2.ModelInfo.IsCoreSuperType(ev))
                                    {
                                        string name = f2.ModelInfo.FhirTypeToFhirTypeName(ev);
                                        var    t    = f2.ModelInfo.GetTypeForFhirType(name);
                                        newContext._cm2.Add(dstu2::Hl7.Fhir.Introspection.ClassMapping.Create(t));
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (item.ElementType != typeof(string)) // (only occurs for extension.url and elementdefinition.id)
                            {
                                newContext._cm2.Add(dstu2::Hl7.Fhir.Introspection.ClassMapping.Create(item.ElementType));
                            }
                        }
                    }
                    catch
                    {
                    }
                }
            }
            return(newContext);
        }
Beispiel #3
0
        private static ExpressionElementContext CheckExpression(Hl7.FhirPath.Expressions.Expression expr, string prefix, ExpressionElementContext context, Action <string, bool, string> AppendResults)
        {
            if (expr is ChildExpression)
            {
                var func         = expr as ChildExpression;
                var focusContext = CheckExpression(func.Focus, prefix + "-- ", context, AppendResults);
                var childContext = focusContext.Child(func.ChildName);
                if (childContext != null)
                {
                    if (focusContext._q4 != null)
                    {
                        if (func.ChildName == "item")
                        {
                            childContext._4is = new List <f4.Questionnaire.ItemComponent>();
                            childContext._4is.AddRange(focusContext._q4.Item);
                        }
                    }
                    if (focusContext._q3 != null)
                    {
                        if (func.ChildName == "item")
                        {
                            childContext._3is = new List <f3.Questionnaire.ItemComponent>();
                            childContext._3is.AddRange(focusContext._q3.Item);
                        }
                    }
                    if (focusContext._q2 != null)
                    {
                        if (func.ChildName == "group")
                        {
                            childContext._2gs = new List <f2.Questionnaire.GroupComponent>();
                            childContext._2gs.Add(focusContext._q2.Group);
                        }
                    }

                    if (focusContext._4is != null)
                    {
                        if (func.ChildName == "item")
                        {
                            childContext._4is = new List <f4.Questionnaire.ItemComponent>();
                            foreach (var item in focusContext._4is)
                            {
                                if (item.Item != null)
                                {
                                    childContext._4is.AddRange(item.Item);
                                }
                            }
                        }
                    }
                    if (focusContext._3is != null)
                    {
                        if (func.ChildName == "item")
                        {
                            childContext._3is = new List <f3.Questionnaire.ItemComponent>();
                            foreach (var item in focusContext._3is)
                            {
                                if (item.Item != null)
                                {
                                    childContext._3is.AddRange(item.Item);
                                }
                            }
                        }
                    }
                    if (focusContext._2gs != null)
                    {
                        if (func.ChildName == "group")
                        {
                            childContext._2gs = new List <f2.Questionnaire.GroupComponent>();
                            foreach (var item in focusContext._2gs)
                            {
                                if (item.Group != null)
                                {
                                    childContext._2gs.AddRange(item.Group);
                                }
                            }
                        }
                        else if (func.ChildName == "question")
                        {
                            childContext._2qs = new List <f2.Questionnaire.QuestionComponent>();
                            foreach (var item in focusContext._2gs)
                            {
                                if (item.Question != null)
                                {
                                    childContext._2qs.AddRange(item.Question);
                                }
                            }
                        }
                    }
                    if (focusContext._2qs != null)
                    {
                        if (func.ChildName == "group")
                        {
                            childContext._2gs = new List <f2.Questionnaire.GroupComponent>();
                            foreach (var item in focusContext._2qs)
                            {
                                if (item.Group != null)
                                {
                                    childContext._2gs.AddRange(item.Group);
                                }
                            }
                        }
                    }
                    AppendResults($"{prefix}{func.ChildName}", false, childContext.Tooltip());
                    return(childContext);
                }
                else
                {
                    AppendResults($"{prefix}{func.ChildName} *invalid property name*", true, null);
                }
                return(context);
            }
            if (expr is FunctionCallExpression)
            {
                var func  = expr as FunctionCallExpression;
                var funcs = _compiler.Symbols.Filter(func.FunctionName, func.Arguments.Count() + 1);
                if (funcs.Count() == 0 && !(expr is BinaryExpression))
                {
                    AppendResults($"{prefix}{func.FunctionName} *invalid function name*", true, null);
                }
                else
                {
                    AppendResults($"{prefix}{func.FunctionName}", false, null);
                }
                var focusContext = CheckExpression(func.Focus, prefix + "-- ", context, AppendResults);

                if (func.FunctionName == "binary.as")
                {
                    if (func.Arguments.Count() != 2)
                    {
                        AppendResults($"{prefix}{func.FunctionName} INVALID AS Operation", true, null);
                        return(focusContext);
                    }
                    var    argContextResult = CheckExpression(func.Arguments.First(), prefix + "    ", focusContext, AppendResults);
                    var    typeArg          = func.Arguments.Skip(1).FirstOrDefault() as ConstantExpression;
                    string typeCast         = typeArg?.Value as string;
                    argContextResult.RestrictToType(typeCast);
                    return(argContextResult);
                }
                else if (func.FunctionName == "resolve")
                {
                    // need to check what the available outcomes of resolving this are, and switch types to this
                }
                else
                {
                    // if this is a where operation and the context inside is a linkId = , then check that the linkId is in context
                    if (func.FunctionName == "where" && func.Arguments.Count() == 1 && (func.Arguments.First() as BinaryExpression)?.Op == "=")
                    {
                        var op = func.Arguments.First() as BinaryExpression;
                        var argContextResult = CheckExpression(op, prefix + "    ", focusContext, AppendResults);

                        // Filter the values that are not in this set
                        focusContext._4is = argContextResult._4is;
                        focusContext._3is = argContextResult._3is;
                        focusContext._2gs = argContextResult._2gs;
                        focusContext._2qs = argContextResult._2qs;
                    }
                    else
                    {
                        foreach (var item in func.Arguments)
                        {
                            var argContextResult = CheckExpression(item, prefix + "    ", focusContext, AppendResults);
                        }
                    }
                    if (func.FunctionName == "binary.=")
                    {
                        ChildExpression    prop  = (ChildExpression)func.Arguments.Where(a => a is ChildExpression).FirstOrDefault();
                        ConstantExpression value = (ConstantExpression)func.Arguments.Where(a => a is ConstantExpression).FirstOrDefault();
                        if (prop?.ChildName == "linkId" && value != null)
                        {
                            var groupLinkIds    = focusContext._2gs?.Select(i => i.LinkId).ToArray();
                            var questionLinkIds = focusContext._2qs?.Select(i => i.LinkId).ToArray();
                            var item4Ids        = focusContext._4is?.Select(i => i.LinkId).ToArray();
                            var item3Ids        = focusContext._3is?.Select(i => i.LinkId).ToArray();

                            // filter out all of the other linkIds from the list
                            focusContext._4is?.RemoveAll(i => i.LinkId != value.Value as string);
                            focusContext._3is?.RemoveAll(i => i.LinkId != value.Value as string);
                            focusContext._2gs?.RemoveAll(g => g.LinkId != value.Value as string);
                            focusContext._2qs?.RemoveAll(q => q.LinkId != value.Value as string);

                            // Validate that there is an item with this value that is reachable
                            if (focusContext._2gs?.Count() == 0 || focusContext._2qs?.Count() == 0)
                            {
                                // this linkId didn't exist in this context!
                                string toolTip = "Available LinkIds:";
                                if (groupLinkIds != null)
                                {
                                    toolTip += $"\r\nGroup: {String.Join(", ", groupLinkIds)}";
                                }
                                if (questionLinkIds != null)
                                {
                                    toolTip += $"\r\nQuestion: {String.Join(", ", questionLinkIds)}";
                                }
                                AppendResults($"{prefix}{func.FunctionName} LinkId is not valid in this context", true, toolTip);
                            }
                            if (focusContext._3is?.Count() == 0)
                            {
                                // this linkId didn't exist in this context!
                                string toolTip = "Available LinkIds:";
                                if (item3Ids != null)
                                {
                                    toolTip += $"\r\nItems: {String.Join(", ", item3Ids)}";
                                }
                                AppendResults($"{prefix}{func.FunctionName} LinkId is not valid in this context", true, toolTip);
                            }
                            if (focusContext._4is?.Count() == 0)
                            {
                                // this linkId didn't exist in this context!
                                string toolTip = "Available LinkIds:";
                                if (item4Ids != null)
                                {
                                    toolTip += $"\r\nItems: {String.Join(", ", item4Ids)}";
                                }
                                AppendResults($"{prefix}{func.FunctionName} LinkId is not valid in this context", true, toolTip);
                            }
                        }
                    }
                }

                return(focusContext);
            }
            //else if (expr is BinaryExpression)
            //{
            //    var func = expr as BinaryExpression;
            //    sb.AppendLine(func.FunctionName);
            //    CheckExpression(func.Left, sb);
            //    sb.AppendLine(func.Op);
            //    CheckExpression(func.Right, sb);
            //    return;
            //}
            else if (expr is ConstantExpression)
            {
                var func = expr as ConstantExpression;
                AppendResults($"{prefix}{func.Value.ToString()} (constant)", false, null);
                return(null); // context doesn't propogate from this
            }
            else if (expr is VariableRefExpression)
            {
                var func = expr as VariableRefExpression;
                // sb.AppendFormat("{0}{1} (variable ref)\r\n", prefix, func.Name);
                return(context);
            }
            AppendResults(expr.GetType().ToString(), false, null);
            return(context);
        }