Beispiel #1
0
        public ParseContext Parse(ODataUriParser parser, ParseContext sourceParseContext)
        {
            SourceParseContext = sourceParseContext;
            var targetParseContext            = new ParseContext();
            var targetQueryableSourceEntities = new List <Dictionary <string, object> >();
            var sourceEdmSetting = sourceParseContext.EdmEntityTypeSettings.FirstOrDefault();
            var targetEdmSetting = new EdmEntityTypeSettings()
            {
                RouteName  = "Groups",
                Personas   = sourceEdmSetting.Personas,
                Properties = new List <EdmEntityTypePropertySetting>()
            };
            var latestStateDictionary = new Dictionary <string, object>();

            var edmEntityType = new EdmEntityType(EdmNamespaceName, "Groups");
            //This may only be used if we client uses Custom.List as aggregation
            var edmComplexType    = new EdmComplexType(EdmNamespaceName, "List");
            var aggregatePropList = new Dictionary <string, AggregateExpression>();
            var applyClause       = parser.ParseApply();

            //We support only single transformation
            if (applyClause.Transformations.Count() > 1)
            {
                throw new FeatureNotSupportedException(ApplyParser, "Multiple Transformations");
            }

            if (applyClause.Transformations.Count() == 0)
            {
                throw new FeatureNotSupportedException(ApplyParser, "Zero Transformations");
            }

            foreach (var transformation in applyClause.Transformations)
            {
                if (transformation.Kind == TransformationNodeKind.GroupBy)
                {
                    var transform = (GroupByTransformationNode)transformation;

                    ///Add all the grouping properties
                    foreach (var groupingProperty in transform.GroupingProperties)
                    {
                        var sourceProperty = sourceEdmSetting.Properties.FirstOrDefault(predicate => predicate.PropertyName.Equals(groupingProperty.Name));

                        edmEntityType.AddStructuralProperty(groupingProperty.Name, groupingProperty.TypeReference.PrimitiveKind());

                        targetEdmSetting.Properties.Add(new EdmEntityTypePropertySetting
                        {
                            PropertyName = sourceProperty.PropertyName,
                            PropertyType = sourceProperty.PropertyType,
                            IsNullable   = sourceProperty.IsNullable
                        });
                    }


                    //Add all the aggregate properties
                    if (transform.ChildTransformations != null)
                    {
                        var aggregationProperties = (AggregateTransformationNode)transform.ChildTransformations;
                        AddAggregationPropertiesToModel(aggregationProperties
                                                        , sourceEdmSetting, edmEntityType, aggregatePropList, targetEdmSetting
                                                        , edmComplexType, latestStateDictionary);
                    }

                    //Register these dynamic types to model
                    sourceParseContext.Model.AddElement(edmEntityType);
                    sourceParseContext.Model.AddElement(edmComplexType);
                    ((EdmEntityContainer)sourceParseContext.Model.EntityContainer).AddEntitySet("Groups", edmEntityType);

                    var fields = transform.GroupingProperties.Select(p => p.Name).ToList();
                    var groups = sourceParseContext.QueryableSourceEntities
                                 .GroupBy(r => fields.ToDictionary(c => c, c => r[c]), new CustomEqualityComparer());

                    var entityRef     = new EdmEntityTypeReference(edmEntityType, true);
                    var collectionRef = new EdmCollectionTypeReference(new EdmCollectionType(entityRef));
                    var collection    = new EdmEntityObjectCollection(collectionRef);
                    latestStateDictionary.Add(RequestFilterConstants.GetEntityTypeKeyName(ApplyParser, StepIndex), entityRef);
                    foreach (var group in groups)
                    {
                        var targetQueryableDictionary = new Dictionary <string, object>();
                        var obj = new EdmEntityObject(edmEntityType);
                        foreach (var prop in fields)
                        {
                            var value = group.Key[prop];
                            obj.TrySetPropertyValue(prop, value);
                            targetQueryableDictionary.Add(prop, value);
                        }
                        AddAggregationPropertyValuesToModel(targetQueryableDictionary, obj, group, edmComplexType, aggregatePropList);
                        collection.Add(obj);
                        targetQueryableSourceEntities.Add(targetQueryableDictionary);
                    }
                    targetParseContext.Result = collection;
                    targetParseContext.Model  = sourceParseContext.Model;
                    targetParseContext.QueryableSourceEntities = targetQueryableSourceEntities;
                    targetParseContext.EdmEntityTypeSettings   = new List <EdmEntityTypeSettings> {
                        targetEdmSetting
                    };
                    targetParseContext.LatestStateDictionary = latestStateDictionary;
                    return(targetParseContext);
                }
                else if (transformation.Kind == TransformationNodeKind.Aggregate)
                {
                    var targetQueryableDictionary = new Dictionary <string, object>();
                    var obj = new EdmEntityObject(edmEntityType);
                    var aggregationProperties = (AggregateTransformationNode)transformation;
                    AddAggregationPropertiesToModel(aggregationProperties
                                                    , sourceEdmSetting, edmEntityType, aggregatePropList, targetEdmSetting
                                                    , edmComplexType, latestStateDictionary);
                    //Register these dynamic types to model
                    sourceParseContext.Model.AddElement(edmEntityType);
                    sourceParseContext.Model.AddElement(edmComplexType);
                    var entityRef     = new EdmEntityTypeReference(edmEntityType, true);
                    var collectionRef = new EdmCollectionTypeReference(new EdmCollectionType(entityRef));
                    var collection    = new EdmEntityObjectCollection(collectionRef);
                    latestStateDictionary.Add(RequestFilterConstants.GetEntityTypeKeyName(ApplyParser, StepIndex), entityRef);
                    AddAggregationPropertyValuesToModel(targetQueryableDictionary, obj, sourceParseContext.QueryableSourceEntities, edmComplexType, aggregatePropList);
                    collection.Add(obj);
                    targetQueryableSourceEntities.Add(targetQueryableDictionary);
                    targetParseContext.Result = collection;
                    targetParseContext.Model  = sourceParseContext.Model;
                    targetParseContext.QueryableSourceEntities = targetQueryableSourceEntities;
                    targetParseContext.EdmEntityTypeSettings   = new List <EdmEntityTypeSettings> {
                        targetEdmSetting
                    };
                    targetParseContext.LatestStateDictionary = latestStateDictionary;
                    return(targetParseContext);
                }
                else
                {
                    throw new FeatureNotSupportedException(ApplyParser, $"Transformation Kind {transformation.Kind} is not supported");
                }
            }
            throw new FeatureNotSupportedException(ApplyParser, "Invalid Apply Clause");
        }