Example #1
0
        private void ButtonCheckExpression_Click(object sender, RoutedEventArgs e)
        {
            var inputNav = GetResourceNavigator();

            if (inputNav == null)
            {
                return;
            }

            // Don't need to cache this, it is cached in the fhir-client
            Hl7.FhirPath.Expressions.Expression expr = null;
            try
            {
                expr = _compiler.Parse(textboxExpression.Text);
            }
            catch (Exception ex)
            {
                SetResults("Expression compilation error:\r\n" + ex.Message, true);
                return;
            }

            if (expr != null)
            {
                try
                {
                    ExpressionElementContext context = new ExpressionElementContext(inputNav.Name);
                    if (inputNav is dstu2::Hl7.Fhir.ElementModel.PocoNavigator pn2)
                    {
                        if (pn2.FhirValue is f2.Questionnaire q)
                        {
                            context._q2 = q;
                        }
                    }
                    else if (inputNav is stu3::Hl7.Fhir.ElementModel.PocoNavigator pn3)
                    {
                        if (pn3.FhirValue is f3.Questionnaire q)
                        {
                            context._q3 = q;
                        }
                    }
                    ResetResults();
                    CheckExpression(expr, "", context);
                }
                catch (Exception ex)
                {
                    SetResults("Expression Check error:\r\n" + ex.Message, true);
                    return;
                }
            }
        }
Example #2
0
        private ExpressionElementContext CheckExpression(Hl7.FhirPath.Expressions.Expression expr, string prefix, ExpressionElementContext context)
        {
            if (expr is ChildExpression)
            {
                var func         = expr as ChildExpression;
                var focusContext = CheckExpression(func.Focus, prefix + "-- ", context);
                var childContext = focusContext.Child(func.ChildName);
                if (childContext != null)
                {
                    if (focusContext._q2 != null)
                    {
                        if (func.ChildName == "group")
                        {
                            childContext._2gs = new List <f2.Questionnaire.GroupComponent>();
                            childContext._2gs.Add(focusContext._q2.Group);
                        }
                    }
                    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);
                }
                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);
                }
                else
                {
                    AppendResults($"{prefix}{func.FunctionName}");
                }
                var focusContext = CheckExpression(func.Focus, prefix + "-- ", context);

                if (func.FunctionName == "binary.as")
                {
                    if (func.Arguments.Count() != 2)
                    {
                        AppendResults($"{prefix}{func.FunctionName} INVALID AS Operation", true);
                        return(focusContext);
                    }
                    var    argContextResult = CheckExpression(func.Arguments.First(), prefix + "    ", focusContext);
                    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);

                        // Filter the values that are not in this set
                        focusContext._2gs = argContextResult._2gs;
                        focusContext._2qs = argContextResult._2qs;
                    }
                    else
                    {
                        foreach (var item in func.Arguments)
                        {
                            var argContextResult = CheckExpression(item, prefix + "    ", focusContext);
                        }
                    }
                    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();

                            // filter out all of the other linkIds from the list
                            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);
                            }
                        }
                    }
                }

                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)");
                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());
            return(context);
        }
Example #3
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))
                {
                    return(null);
                }

                var newContext = new ExpressionElementContext();

                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.ElementType != typeof(string)) // (only occurs for extension.url and elementdefinition.id)
                                {
                                    newContext._cm3.Add(stu3::Hl7.Fhir.Introspection.ClassMapping.Create(item.ElementType));
                                }
                            }
                        }
                        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);
            }