public void ParseApplyWithNestedAggregation()
        {
            string apply = "groupby((UnitPrice), aggregate(Sales($count as Count)))";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(1);

            List <QueryToken> transformations = actual.ToList();

            // verify groupby
            GroupByToken groupBy = transformations[0] as GroupByToken;

            groupBy.Should().NotBeNull();

            VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy);

            groupBy.Properties.Should().HaveCount(1);
            groupBy.Child.Should().NotBeNull();

            AggregateToken groupByAggregate = groupBy.Child as AggregateToken;

            groupByAggregate.AggregateExpressions.Should().HaveCount(1);

            EntitySetAggregateToken entitySetAggregate = groupByAggregate.AggregateExpressions.First() as EntitySetAggregateToken;

            entitySetAggregate.Should().NotBeNull();

            entitySetAggregate.EntitySet.ShouldBeEndPathToken("Sales");
            VerifyAggregateExpressionToken("$count", AggregationMethodDefinition.VirtualPropertyCount, "Count", entitySetAggregate.Expressions.First() as AggregateExpressionToken);
        }
        private static void VerifyGroupByTokenProperties(IEnumerable <string> expectedEndPathIdentifiers, GroupByToken actual)
        {
            actual.Should().NotBeNull();

            if (expectedEndPathIdentifiers == null || !expectedEndPathIdentifiers.Any())
            {
                actual.Properties.Should().HaveCount(0);
            }
            else
            {
                actual.Properties.Should().HaveCount(expectedEndPathIdentifiers.Count());

                List <string> expectedIdentifierList = expectedEndPathIdentifiers.ToList();
                int           i = 0;
                foreach (EndPathToken actualProperty in actual.Properties)
                {
                    actualProperty.Should().NotBeNull();

                    EndPathToken endPathToken = actualProperty as EndPathToken;
                    endPathToken.Should().NotBeNull();
                    endPathToken.Identifier.Should().Be(expectedIdentifierList[i]);
                    i++;
                }
            }
        }
        public void ParseApplyWithSingleGroupByPropertyShouldReturnGroupByToken()
        {
            string apply = "groupby((UnitPrice))";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(1);

            GroupByToken groupBy = actual.First() as GroupByToken;

            groupBy.Should().NotBeNull();

            VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy);
        }
        public void ParseApplyWithNestedFunctionAggregation()
        {
            string apply = "groupby((UnitPrice), aggregate(Sales($count as Count,  cast(SalesPrice, Edm.Decimal)  with average as RetailPrice)))";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(1);

            List <QueryToken> transformations = actual.ToList();

            // verify groupby
            GroupByToken groupBy = transformations[0] as GroupByToken;

            groupBy.Should().NotBeNull();

            VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy);

            groupBy.Properties.Should().HaveCount(1);
            groupBy.Child.Should().NotBeNull();

            AggregateToken groupByAggregate = groupBy.Child as AggregateToken;

            groupByAggregate.AggregateExpressions.Should().HaveCount(1);

            EntitySetAggregateToken entitySetAggregate = groupByAggregate.AggregateExpressions.First() as EntitySetAggregateToken;

            entitySetAggregate.Should().NotBeNull();

            entitySetAggregate.EntitySet.ShouldBeEndPathToken("Sales");
            entitySetAggregate.Expressions.Should().HaveCount(2);
            VerifyAggregateExpressionToken("$count", AggregationMethodDefinition.VirtualPropertyCount, "Count", entitySetAggregate.Expressions.First() as AggregateExpressionToken);

            AggregateExpressionToken funcAggregate = entitySetAggregate.Expressions.Last() as AggregateExpressionToken;

            funcAggregate.Should().NotBeNull();
            funcAggregate.Alias.ShouldBeEquivalentTo("RetailPrice");
            funcAggregate.Method.Should().Equals(AggregationMethodDefinition.Average);

            FunctionCallToken funcToken = funcAggregate.Expression as FunctionCallToken;

            funcToken.Should().NotBeNull();
            funcToken.Name.ShouldBeEquivalentTo("cast");
        }
        public void ParseApplyWithMultipleTransformationShouldReturnTransformations()
        {
            string apply = "groupby((UnitPrice), aggregate(SalesPrice with average as RetailPrice))/filter(UnitPrice eq 5)/aggregate(CustomerId with sum as Total, SharePrice with countdistinct as SharePriceDistinctCount)";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(3);

            List <QueryToken> transformations = actual.ToList();

            // verify groupby
            GroupByToken groupBy = transformations[0] as GroupByToken;

            groupBy.Should().NotBeNull();

            VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy);


            groupBy.Properties.Should().HaveCount(1);
            groupBy.Child.Should().NotBeNull();

            AggregateToken groupByAggregate = groupBy.Child as AggregateToken;

            groupByAggregate.AggregateExpressions.Should().HaveCount(1);
            VerifyAggregateExpressionToken("SalesPrice", AggregationMethodDefinition.Average, "RetailPrice", groupByAggregate.AggregateExpressions.First() as AggregateExpressionToken);

            // verify filter
            BinaryOperatorToken filter = transformations[1] as BinaryOperatorToken;

            VerifyBinaryOperatorToken <int>("UnitPrice", BinaryOperatorKind.Equal, 5, filter);

            // verify aggregate
            AggregateToken aggregate = transformations[2] as AggregateToken;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(2);

            List <AggregateTokenBase> aggregateExpressions = aggregate.AggregateExpressions.ToList();

            VerifyAggregateExpressionToken("CustomerId", AggregationMethodDefinition.Sum, "Total", aggregateExpressions[0] as AggregateExpressionToken);
            VerifyAggregateExpressionToken("SharePrice", AggregationMethodDefinition.CountDistinct, "SharePriceDistinctCount", aggregateExpressions[1] as AggregateExpressionToken);
        }