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}"); } }
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); })); }
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)); }
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); }
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); } }
// 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)); }
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)); }