public void AddToClause(QueueItem clause)
        {
            const string invalidQueryText = "invalid query";

            if (clause is null)
            {
                throw new ArgumentException(invalidQueryText);
            }
            else if (clause.Representation == TextRepresentation.ListOfExpands || clause.Representation == TextRepresentation.ListOfSortings)
            {
                foreach (var child in clause.Children.Select(x => x.Item2))
                {
                    AddToClause(child);
                }
            }
            else if (clause.Representation == TextRepresentation.SortProperty)
            {
                var direction = clause.Children.Last().Item2.Root.Value.Text == "asc" ? SortDirection.Ascending : SortDirection.Descending;
                var child     = clause.Children.First().Item2;
                ResultList.Add(ITuple.Create(SelectClauseParser <TRootQueryType> .PathAndPropertyFromExpandItem(child, Graph, RootQueryType), direction));
            }
            else if (clause.Representation == TextRepresentation.ExpandProperty)
            {
                ResultList.Add(ITuple.Create(SelectClauseParser <TRootQueryType> .PathAndPropertyFromExpandItem(clause, Graph, RootQueryType), SortDirection.Ascending));
            }
            else
            {
                throw new ArgumentException($"{invalidQueryText} - Unrecognized term: {clause.Root.Value.Text}");
            }
        }
Exemple #2
0
        public static TGrouping ListOfClauseExpressions()
        {
            var expand = TextRepresentation.ExpandExpression;
            var filter = TextRepresentation.FilterExpression;
            var select = TextRepresentation.SelectExpression;

            var clause = $"({expand}|{filter}|{select})";

            return(Create($"{clause}({TextRepresentation.SemiColin}{clause})*", list =>
            {
                var root = new Vertex(TInfo.FromRepresentation(TextRepresentation.ListOfClause, typeof(TInfo)));

                bool IsClause(QueueItem item)
                {
                    if (item.Representation == expand)
                    {
                        return true;
                    }
                    if (item.Representation == filter)
                    {
                        return true;
                    }
                    if (item.Representation == select)
                    {
                        return true;
                    }
                    return false;
                }

                var childrenWithEdge = list.Where(IsClause).Select(x => ITuple.Create(new Edge(root, x.Root), x));
                return ITuple.Create(new QueueItem(root, childrenWithEdge), list.Count - 1);
            }));
        }
Exemple #3
0
        public async Task ApiTests_PostWithChildren_People_EntityReturned()
        {
            var count        = 1;
            var peopleFake   = FakePerson();
            var postedPeople = await PostPeople(peopleFake, count);

            var postedChildren = await PostChildren(FakeChild(), count);

            var toPatch = postedPeople.Select(p =>
            {
                var toModify        = ModifyPerson(p);
                toModify.FavoriteId = postedChildren.Select(x => x.Id).First();
                return(ITuple.Create(p.Id, toModify));
            }).ToList();

            await PatchPeople(toPatch);

            var result = await GetPeople_OK("Favorite");

            // Then
            result.Should().NotBeNullOrEmpty();
            result.Should().HaveCount(count);

            foreach (var dto in result)
            {
                dto.Should().NotBeNull();
                dto.Id.Should().BeGreaterThan(0);
                dto.Name.Should().BeOneOf(postedPeople.Select(x => x.Name));
                dto.Region_code.Should().BeOneOf(postedPeople.Select(x => x.Region_code));
                dto.Partner.Should().BeNull();
                dto.Favorite.Should().NotBeNull();
                dto.Children.Should().BeNullOrEmpty();
            }
        }
        public static QueryTree TranslateTree(GraphImplementations.Schema.Tree expandTree, IEnumerable <GraphImplementations.Schema.PathToProperty> selections)
        {
            var schemaExpandPaths        = expandTree.EnumerateAllPaths(x => new GraphImplementations.Schema.Path(x)).ToList();
            var filteredPaths            = selections.Where(sel => schemaExpandPaths.Contains(sel));
            var typeIdByPropertySelected = new[] {
                filteredPaths.Select(f => ITuple.Create(f.Last().From.Value.TypeId, f.Property)),
                filteredPaths.Select(f => ITuple.Create(f.Last().To.Value.TypeId, f.Property)),
            }.SelectMany(x => x)
            .GroupBy(tuple => tuple.Item1)                                                                 // group by schema vertex type id.
            .Select(x => ITuple.Create(x.Key, new List <Property>(x.Select(tup => tup.Item2).Distinct()))) // get list of tuple <vertex, property>
            .ToList();
            var typeIdByNavigationSelected = new[] {
                schemaExpandPaths.Select(f => ITuple.Create <int, Property>(f.Last().From.Value.TypeId, f.Last().Value)),
                schemaExpandPaths.Select(f => ITuple.Create <int, Property>(f.Last().To.Value.TypeId, f.Last().Value))
            }.SelectMany(x => x)
            .GroupBy(tuple => tuple.Item1)                                                                 // group by schema vertex type id.
            .Select(x => ITuple.Create(x.Key, new List <Property>(x.Select(tup => tup.Item2).Distinct()))) // get list of tuple <vertex, property>
            .ToList();


            // could throw an error here or something if there are select paths outside of the expand tree paths.

            var expandSubGraph = expandTree.Flatten();

            IEnumerable <Property> GetSelectionListForQueryClass(int typeId)
            {
                // property list for the vertex(of the same type(id))
                var pList  = typeIdByPropertySelected.FirstOrDefault(p => p.Item1 == typeId);
                var result = new List <Property>();

                // if it's empty, return a list of normal properties.
                if (pList is null || !pList.Item2.Any())
                {
                    result.AddRange(expandSubGraph.Vertices.First(x => x.Value.TypeId == typeId).Value.Properties.Where(p => p.IsPrimitive));
                }
Exemple #5
0
        public ClassInfoUtility(Type t)
        {
            this.Type = t;
            IEnumerable <string> GetNames(IEnumerable <PropertyInfo> infoList) => infoList.Select(p => p.Name);

            Properties      = t.GetProperties().Where(x => x.CanRead).ToList().AsReadOnly();
            PropertyAndType = Properties.ToDictionary(p => p.Name, p => p.PropertyType);

            NonExpandableProperties = Properties.Where(p => PrimitiveTypeWhiteList.Contains(p.PropertyType)).ToList().AsReadOnly();
            var nonExpandProperties = NonExpandableProperties;

            ExpandableProperties = Properties.Where(p => !nonExpandProperties.Contains(p)).ToList().AsReadOnly();
            //(!x.PropertyType.Assembly.GetName().Name.StartsWith("System.") ||
            //(x.PropertyType.IsNestedPublic || x.PropertyType.IsInterface))
            //);
            Collections = ExpandableProperties.Where(x => typeof(IBaseList).IsAssignableFrom(x.PropertyType)).ToList().AsReadOnly();

            var collections = Collections;

            NavigationProperties = ExpandableProperties.Where(p => !collections.Contains(p)).ToList().AsReadOnly();

            PropertyNames              = GetNames(Properties).ToList().AsReadOnly();
            ExpandablePropertyNames    = GetNames(ExpandableProperties).ToList().AsReadOnly();
            NonExpandablePropertyNames = GetNames(NonExpandableProperties).ToList().AsReadOnly();
            CollectionNames            = GetNames(Collections).ToList().AsReadOnly();
            NavigationPropertyNames    = GetNames(NavigationProperties).ToList().AsReadOnly();

            AccessProperties = Properties.Select(p => ITuple.Create <string, Func <object, object> >(p.Name, p.GetValue))
                               .ToDictionary(x => x.Item1, x => x.Item2);
        }
Exemple #6
0
        private static TGrouping[] _parseGrouping(ITuple <string, Func <IList <QueueItem>, ITuple <QueueItem, int> > > term)
        {
            var pattern = term.Item1;
            var func    = term.Item2;
            var regex   = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Singleline);

            return(new[] { ITuple.Create(regex, func) });
        }
 public void AddToClause(QueueItem clause)
 {
     if (Result is null)
     {
         Result = clause;
     }
     else
     {
         var and               = new TextInfo("and", TextRepresentation.LogicalComparison);
         var rootAnd           = new ParserVertex(and);
         var childrenWithEdges = new[] {
             ITuple.Create(new ParserEdge(rootAnd, clause.Root), clause),
             ITuple.Create(new ParserEdge(rootAnd, Result.Root), Result)
         };
         Result = new QueueItem(rootAnd, childrenWithEdges);
     }
 }
Exemple #8
0
            // note: this mehtod is immutable - it does not change the current state of the "source" argument.
            private QueueItem AppendPathToQueueItem(IEnumerable <SchemaEdge> prependEdges, QueueItem source)
            {
                if (!prependEdges.Any())
                {
                    return(source);
                }
                if (source.Representation == TextRepresentation.ExpandProperty)
                {
                    var text  = prependEdges.First().Value.Name;
                    var root  = new ParserVertex(new TInfo(text, TextRepresentation.ExpandProperty));
                    var child = AppendPathToQueueItem(prependEdges.Skip(1), source);
                    return(new QueueItem(root, new[] { ITuple.Create(new ParserEdge(root, child.Root), child) }));
                }
                var children          = source.Children.Select(x => AppendPathToQueueItem(prependEdges, x.Item2));
                var childrenWithEdges = children.Select(child => ITuple.Create(new ParserEdge(source.Root, child.Root), child));

                return(new QueueItem(source.Root, childrenWithEdges));
            }
Exemple #9
0
 private static TGrouping Create(string pattern, Func <IList <QueueItem>, ITuple <QueueItem, int> > addFunc) => ITuple.Create(pattern, addFunc);
        public static IEnumerable <TGrouping> AddTermsForFilter()
        {
            yield return(Create(TextRepresentation.Inverse + $"({TextRepresentation.BooleanValue}|{TextRepresentation.ExpandProperty})", list =>
            {
                var root = new Vertex(new TInfo("!", TextRepresentation.BooleanValue));
                var child = list[1];
                var edge = new Edge(root, child.Root);
                return ITuple.Create(new QueueItem(root, new[] { ITuple.Create(edge, new QueueItem(child.Root)) }), 1);
            }));

            ITuple <QueueItem, int> valueSomethingValue(IList <QueueItem> list, string rootText = null)
            {
                if (rootText is null)
                {
                    rootText = TextRepresentation.ValueComparison;
                }
                var root       = new Vertex(new TInfo(rootText, TextRepresentation.BooleanValue));
                var left       = list[0];
                var comparitor = list[1];
                var right      = list[2];
                var edgeLeft   = new Edge(root, left.Root);
                var edgeMiddle = new Edge(root, comparitor.Root);
                var edgeRight  = new Edge(root, right.Root);

                return(ITuple.Create(new QueueItem(root, new[] {
                    ITuple.Create(edgeLeft, left),
                    ITuple.Create(edgeMiddle, comparitor),
                    ITuple.Create(edgeRight, right),
                }), 2));
            }

            ITuple <QueueItem, int> valueItemValue(IList <QueueItem> list) => valueSomethingValue(list);

            string valueComparisonPattern(string a, string b) => a + TextRepresentation.ValueComparison + b;

            // value to value
            yield return(Create(valueComparisonPattern(TextRepresentation.BooleanValue, TextRepresentation.BooleanValue), valueItemValue));

            yield return(Create(valueComparisonPattern(TextRepresentation.TextValue, TextRepresentation.TextValue), valueItemValue));

            yield return(Create(valueComparisonPattern(TextRepresentation.NumberValue, TextRepresentation.NumberValue), valueItemValue));

            yield return(Create(valueComparisonPattern(TextRepresentation.DateValue, TextRepresentation.DateValue), valueItemValue));

            // property to value
            yield return(Create(valueComparisonPattern(TextRepresentation.ExpandProperty, TextRepresentation.BooleanValue), valueItemValue));

            yield return(Create(valueComparisonPattern(TextRepresentation.ExpandProperty, TextRepresentation.TextValue), valueItemValue));

            yield return(Create(valueComparisonPattern(TextRepresentation.ExpandProperty, TextRepresentation.NumberValue), valueItemValue));

            yield return(Create(valueComparisonPattern(TextRepresentation.ExpandProperty, TextRepresentation.DateValue), valueItemValue));

            // value to property
            yield return(Create(valueComparisonPattern(TextRepresentation.BooleanValue, TextRepresentation.ExpandProperty), valueItemValue));

            yield return(Create(valueComparisonPattern(TextRepresentation.TextValue, TextRepresentation.ExpandProperty), valueItemValue));

            yield return(Create(valueComparisonPattern(TextRepresentation.NumberValue, TextRepresentation.ExpandProperty), valueItemValue));

            yield return(Create(valueComparisonPattern(TextRepresentation.DateValue, TextRepresentation.ExpandProperty), valueItemValue));

            // property to property
            yield return(Create(valueComparisonPattern(TextRepresentation.ExpandProperty, TextRepresentation.ExpandProperty), valueItemValue));

            var anyValueTypeRegex = $"({TextRepresentation.BooleanValue}|{TextRepresentation.NumberValue}|{TextRepresentation.TextValue}|{TextRepresentation.DateValue}|{TextRepresentation.ExpandProperty})";
            var strTypeRegex      = $"({TextRepresentation.TextValue}|{TextRepresentation.ExpandProperty})";

            // string functions
            // length(x)
            var lenRegex = $"{TextRepresentation.StrLength}{TextRepresentation.OpenParenthesis}{strTypeRegex}{TextRepresentation.CloseParenthesis}";

            yield return(Create(lenRegex, list =>
            {
                var root = new Vertex(new TInfo(TextRepresentation.StrLength, TextRepresentation.NumberValue));
                var lengthTree = list[2];
                var edgeRight = new Edge(root, lengthTree.Root);
                return ITuple.Create(new QueueItem(root, new[] {
                    ITuple.Create(edgeRight, lengthTree),
                }), 3);
            }));

            string StringFunctionRegexHelper(string fctn, int argCount)
            {
                var result = $"{fctn}{TextRepresentation.OpenParenthesis}";
                var sb     = new StringBuilder(result);

                for (int i = 0; i < argCount; ++i)
                {
                    if (i == argCount - 1)
                    {
                        sb.Append(strTypeRegex);
                    }
                    else
                    {
                        sb.Append($"{strTypeRegex}{TextRepresentation.Comma}");
                    }
                }
                sb.Append($"{TextRepresentation.CloseParenthesis}");
                return(sb.ToString());
            }

            ITuple <QueueItem, int> strFunctionHelper(IList <QueueItem> list, string rootText, string rootRepresentation)
            {
                var totalCount            = list.Count;
                var totalAfterWastedItems = totalCount - 2;
                var total = totalAfterWastedItems / 2;

                var root = new Vertex(new TInfo(rootText, rootRepresentation));

                var strArgs = new List <QueueItem>(total);

                for (var i = 0; i < total; ++i)
                {
                    strArgs.Add(list[(i * 2) + 2]);
                }

                var edgeArgs = new List <Edge>(total);

                foreach (var vertex in strArgs)
                {
                    edgeArgs.Add(new Edge(root, vertex.Root));
                }

                var children = new List <ITuple <Edge, QueueItem> >(total);

                for (var i = 0; i < strArgs.Count && i < edgeArgs.Count; ++i)
                {
                    children.Add(ITuple.Create(edgeArgs[i], strArgs[i]));
                }

                return(ITuple.Create(new QueueItem(root, children), list.Count - 1));
            }

            var endsWithRegex = StringFunctionRegexHelper(TextRepresentation.StrEndsWith, 2);

            yield return(Create(endsWithRegex, list => strFunctionHelper(list, TextRepresentation.StrEndsWith, TextRepresentation.BooleanValue)));

            var startsWithRegex = StringFunctionRegexHelper(TextRepresentation.StrStartsWith, 2);

            yield return(Create(startsWithRegex, list => strFunctionHelper(list, TextRepresentation.StrStartsWith, TextRepresentation.BooleanValue)));

            var indexOfRegex = StringFunctionRegexHelper(TextRepresentation.StrIndexOf, 2);

            yield return(Create(indexOfRegex, list => strFunctionHelper(list, TextRepresentation.StrIndexOf, TextRepresentation.NumberValue)));

            var containsRegex = StringFunctionRegexHelper(TextRepresentation.StrContains, 2);

            yield return(Create(containsRegex, list => strFunctionHelper(list, TextRepresentation.StrContains, TextRepresentation.BooleanValue)));

            var replaceRegex = StringFunctionRegexHelper(TextRepresentation.StrReplace, 3);

            yield return(Create(replaceRegex, list => strFunctionHelper(list, TextRepresentation.StrReplace, TextRepresentation.TextValue)));

            var toLowerRegex = StringFunctionRegexHelper(TextRepresentation.StrToLower, 1);

            yield return(Create(toLowerRegex, list => strFunctionHelper(list, TextRepresentation.StrToLower, TextRepresentation.TextValue)));

            var toUpperRegex = StringFunctionRegexHelper(TextRepresentation.StrToUpper, 1);

            yield return(Create(toUpperRegex, list => strFunctionHelper(list, TextRepresentation.StrToUpper, TextRepresentation.TextValue)));

            var concatRegex = StringFunctionRegexHelper(TextRepresentation.StrConcat, 2);

            yield return(Create(concatRegex, list => strFunctionHelper(list, TextRepresentation.StrConcat, TextRepresentation.TextValue)));

            var trimRegex = StringFunctionRegexHelper(TextRepresentation.StrTrim, 1);

            yield return(Create(trimRegex, list => strFunctionHelper(list, TextRepresentation.StrTrim, TextRepresentation.TextValue)));

            string StringFunctionRegexHelperWithIntArgs(string fctn, int argCount)
            {
                var sb = new StringBuilder($"{fctn}{TextRepresentation.OpenParenthesis}");

                for (int i = 0; i < argCount; ++i)
                {
                    if (i == 0)
                    {
                        sb.Append(strTypeRegex);
                    }
                    else
                    {
                        sb.Append(TextRepresentation.NumberValue);
                    }

                    if (i != argCount - 1)
                    {
                        sb.Append(TextRepresentation.Comma);
                    }
                }
                sb.Append(TextRepresentation.CloseParenthesis);
                return(sb.ToString());
            }

            var substring1Regex = StringFunctionRegexHelperWithIntArgs(TextRepresentation.StrSubString, 2);

            yield return(Create(substring1Regex, list => strFunctionHelper(list, TextRepresentation.StrSubString, TextRepresentation.TextValue)));

            var substring2Regex = StringFunctionRegexHelperWithIntArgs(TextRepresentation.StrSubString, 3);

            yield return(Create(substring2Regex, list => strFunctionHelper(list, TextRepresentation.StrSubString, TextRepresentation.TextValue)));

            // ( )
            ITuple <QueueItem, int> undoGrouping(IList <QueueItem> list) => ITuple.Create(list[1], 2);

            yield return(Create(TextRepresentation.OpenParenthesis + anyValueTypeRegex + TextRepresentation.CloseParenthesis, undoGrouping));

            // Logical comparisons. Ie and or not, etc.
            string logicComparisonPattern(string a, string b) => $"{a}{TextRepresentation.LogicalComparison}{b}";
            ITuple <QueueItem, int> valueLogicValue(IList <QueueItem> list) => valueSomethingValue(list, TextRepresentation.LogicalComparison);

            yield return(Create(logicComparisonPattern(TextRepresentation.BooleanValue, TextRepresentation.BooleanValue), valueLogicValue));

            yield return(Create(logicComparisonPattern(TextRepresentation.ExpandProperty, TextRepresentation.BooleanValue), valueLogicValue));

            yield return(Create(logicComparisonPattern(TextRepresentation.BooleanValue, TextRepresentation.ExpandProperty), valueLogicValue));

            yield return(Create(logicComparisonPattern(TextRepresentation.ExpandProperty, TextRepresentation.ExpandProperty), valueLogicValue));
        }