Exemplo n.º 1
0
 /// <summary>
 /// Build a segment representing a navigation property.
 /// </summary>
 /// <param name="path">Path to perform the computation on.</param>
 /// <param name="navigationProperty">The navigation property this segment represents.</param>
 /// <param name="navigationSource">The navigation source of the entities targetted by this navigation property. This can be null.</param>
 /// <returns>The ODataPath with navigation property appended in the end in the end</returns>
 public static ODataPath AppendNavigationPropertySegment(this ODataPath path, IEdmNavigationProperty navigationProperty, IEdmNavigationSource navigationSource)
 {
     var newPath = new ODataPath(path);
     NavigationPropertySegment np = new NavigationPropertySegment(navigationProperty, navigationSource);
     newPath.Add(np);
     return newPath;
 }
 public void SingleResultSetCorrectly()
 {
     NavigationPropertySegment navigationPropertySegment1 = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);
     navigationPropertySegment1.SingleResult.Should().BeTrue();
     NavigationPropertySegment navigationPropertySegment2 = new NavigationPropertySegment(HardCodedTestModel.GetDogMyPeopleNavProp(), null);
     navigationPropertySegment2.SingleResult.Should().BeFalse();
 }
 public void InequalityIsCorrect()
 {
     NavigationPropertySegment navigationPropertySegment1 = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);
     NavigationPropertySegment navigationPropertySegment2 = new NavigationPropertySegment(HardCodedTestModel.GetDogMyPeopleNavProp(), null);
     CountSegment segment = CountSegment.Instance;
     navigationPropertySegment1.Equals(navigationPropertySegment2).Should().BeFalse();
     navigationPropertySegment1.Equals(segment).Should().BeFalse();
 }
Exemplo n.º 4
0
 public override bool Translate(NavigationPropertySegment segment)
 {
     return(GetNextSegment() is NavigationPropertySegment navigationPropertySegment && navigationPropertySegment.NavigationProperty == segment.NavigationProperty);
 }
Exemplo n.º 5
0
 public override string Translate(NavigationPropertySegment segment)
 {
     return(string.Format("{{NavProp:[{0}]}}", segment.NavigationProperty.Name));
 }
Exemplo n.º 6
0
        public void ODataUriBuilderWithKeyAsSegment()
        {
            Uri            fullUri        = new Uri("http://www.example.com/People/1?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID&$expand=MyDog%2CMyCat/$ref&$top=1&$skip=2&$count=false");
            ODataUriParser oDataUriParser = new ODataUriParser(this.GetModel(), serviceRoot, fullUri);

            oDataUriParser.UrlConventions = ODataUrlConventions.KeyAsSegment;
            SetODataUriParserSettingsTo(this.settings, oDataUriParser.Settings);
            ODataUri odataUri = oDataUriParser.ParseUri();

            //verify path
            EntitySetSegment entitySet  = (EntitySetSegment)odataUri.Path.FirstSegment;
            KeySegment       keySegment = (KeySegment)odataUri.Path.LastSegment;
            IEnumerable <KeyValuePair <string, object> > keyValuePairs = keySegment.Keys;

            Assert.AreEqual(odataUri.Path.Count, 2);
            Assert.AreEqual(entitySet.EntitySet.Name, "People");
            foreach (var keyValuePair in keyValuePairs)
            {
                Assert.AreEqual(keyValuePair.Key, "ID");
                Assert.AreEqual(keyValuePair.Value, 1);
            }

            //verify $filter
            BinaryOperatorNode            binaryOperator      = (BinaryOperatorNode)odataUri.Filter.Expression;
            SingleValuePropertyAccessNode singleValueProperty = (SingleValuePropertyAccessNode)binaryOperator.Left;
            SingleNavigationNode          singleNavigation    = (SingleNavigationNode)singleValueProperty.Source;
            ConstantNode constantNode = (ConstantNode)binaryOperator.Right;

            Assert.AreEqual(binaryOperator.OperatorKind, BinaryOperatorKind.Equal);
            Assert.AreEqual(singleValueProperty.Property.Name, "Color");
            Assert.AreEqual(singleNavigation.NavigationProperty.Name, "MyDog");
            Assert.AreEqual(constantNode.LiteralText, "'Brown'");

            //verify $select and $expand
            IEnumerable <SelectItem> selectItems = odataUri.SelectAndExpand.SelectedItems;
            IEnumerable <ExpandedNavigationSelectItem> expandedNavigationSelectItem = selectItems.Where(I => I.GetType() == typeof(ExpandedNavigationSelectItem)).OfType <ExpandedNavigationSelectItem>();
            IEnumerable <ExpandedReferenceSelectItem>  expandedReferenceSelectItem  = selectItems.Where(I => I.GetType() == typeof(ExpandedReferenceSelectItem)).OfType <ExpandedReferenceSelectItem>();
            IEnumerable <PathSelectItem> pathSelectItem = selectItems.Where(I => I.GetType() == typeof(PathSelectItem)).OfType <PathSelectItem>();

            Assert.AreEqual(expandedNavigationSelectItem.Count(), 1);
            Assert.AreEqual(expandedReferenceSelectItem.Count(), 1);
            Assert.AreEqual(pathSelectItem.Count(), 3);
            NavigationPropertySegment navigationProperty = (NavigationPropertySegment)expandedNavigationSelectItem.First().PathToNavigationProperty.FirstSegment;

            Assert.AreEqual(navigationProperty.NavigationProperty.Name, "MyDog");
            navigationProperty = (NavigationPropertySegment)expandedReferenceSelectItem.First().PathToNavigationProperty.FirstSegment;
            Assert.AreEqual(navigationProperty.NavigationProperty.Name, "MyCat");

            //verify $top
            Assert.AreEqual(odataUri.Top, 1);

            //verify $skip
            Assert.AreEqual(odataUri.Skip, 2);

            //verify $count
            Assert.AreEqual(odataUri.QueryCount, false);

            ODataUriBuilder uriBuilderWithKeyAsSegment = new ODataUriBuilder(ODataUrlConventions.KeyAsSegment, odataUri);
            Uri             actualUri = uriBuilderWithKeyAsSegment.BuildUri();

            Assert.AreEqual(new Uri("http://www.example.com/People/1?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyDog%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$top=1&$skip=2&$count=false"), actualUri);
        }
 /// <summary>
 /// Handle a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">the segment to Handle</param>
 public virtual void Handle(NavigationPropertySegment segment)
 {
     throw new NotImplementedException();
 }
        private static bool TryBindAsDeclaredProperty(PathSegmentToken tokenIn, IEdmStructuredType edmType, ODataUriResolver resolver, out ODataPathSegment segment)
        {
            IEdmProperty prop = resolver.ResolveProperty(edmType, tokenIn.Identifier);
            if (prop == null)
            {
                segment = null;
                return false;
            }

            if (prop.PropertyKind == EdmPropertyKind.Structural)
            {
                segment = new PropertySegment((IEdmStructuralProperty)prop);
                return true;
            }

            if (prop.PropertyKind == EdmPropertyKind.Navigation)
            {
                segment = new NavigationPropertySegment((IEdmNavigationProperty)prop, null /*TODO: set*/);
                return true;
            }

            throw new ODataException(ODataErrorStrings.SelectExpandBinder_UnknownPropertyType(prop.Name));
        }
Exemplo n.º 9
0
        private void BuildSelections(
            SelectExpandClause selectExpandClause,
            HashSet <IEdmStructuralProperty> allStructuralProperties,
            HashSet <IEdmNavigationProperty> allNavigationProperties,
            HashSet <IEdmAction> allActions,
            HashSet <IEdmFunction> allFunctions)
        {
            foreach (SelectItem selectItem in selectExpandClause.SelectedItems)
            {
                if (selectItem is ExpandedNavigationSelectItem)
                {
                    continue;
                }

                PathSelectItem pathSelectItem = selectItem as PathSelectItem;

                if (pathSelectItem != null)
                {
                    ValidatePathIsSupported(pathSelectItem.SelectedPath);
                    ODataPathSegment segment = pathSelectItem.SelectedPath.LastSegment;

                    NavigationPropertySegment navigationPropertySegment = segment as NavigationPropertySegment;
                    if (navigationPropertySegment != null)
                    {
                        IEdmNavigationProperty navigationProperty = navigationPropertySegment.NavigationProperty;
                        if (allNavigationProperties.Contains(navigationProperty))
                        {
                            SelectedNavigationProperties.Add(navigationProperty);
                        }
                        continue;
                    }

                    PropertySegment structuralPropertySegment = segment as PropertySegment;
                    if (structuralPropertySegment != null)
                    {
                        IEdmStructuralProperty structuralProperty = structuralPropertySegment.Property;
                        if (allStructuralProperties.Contains(structuralProperty))
                        {
                            SelectedStructuralProperties.Add(structuralProperty);
                        }
                        continue;
                    }

                    OperationSegment operationSegment = segment as OperationSegment;
                    if (operationSegment != null)
                    {
                        AddOperations(allActions, allFunctions, operationSegment);
                        continue;
                    }
                    throw new ODataException(Error.Format(SRResources.SelectionTypeNotSupported, segment.GetType().Name));
                }

                WildcardSelectItem wildCardSelectItem = selectItem as WildcardSelectItem;
                if (wildCardSelectItem != null)
                {
                    SelectedStructuralProperties = allStructuralProperties;
                    SelectedNavigationProperties = allNavigationProperties;
                    continue;
                }

                NamespaceQualifiedWildcardSelectItem wildCardActionSelection = selectItem as NamespaceQualifiedWildcardSelectItem;
                if (wildCardActionSelection != null)
                {
                    SelectedActions   = allActions;
                    SelectedFunctions = allFunctions;
                    continue;
                }

                throw new ODataException(Error.Format(SRResources.SelectionTypeNotSupported, selectItem.GetType().Name));
            }
        }
Exemplo n.º 10
0
        public void NavPropSetCorrectly()
        {
            NavigationPropertySegment segment = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);

            segment.NavigationProperty.Should().BeSameAs(HardCodedTestModel.GetPersonMyDogNavProp());
        }
 public void TargetEdmTypeShouldBeNavPropTypeDefinition()
 {
     NavigationPropertySegment navigationPropertySegment = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);
     navigationPropertySegment.TargetEdmType.Should().BeSameAs(HardCodedTestModel.GetPersonMyDogNavProp().Type.Definition);
 }
Exemplo n.º 12
0
        public void TargetEdmTypeShouldBeNavPropTypeDefinition()
        {
            NavigationPropertySegment navigationPropertySegment = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);

            navigationPropertySegment.TargetEdmType.Should().BeSameAs(HardCodedTestModel.GetPersonMyDogNavProp().Type.Definition);
        }
Exemplo n.º 13
0
        public void TargetKindShouldBeResource()
        {
            NavigationPropertySegment navigationPropertySegment = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);

            navigationPropertySegment.TargetKind.Should().Be(RequestTargetKind.Resource);
        }
Exemplo n.º 14
0
        public void IdentifierShouldBeNavPropName()
        {
            NavigationPropertySegment navigationPropertySegment = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);

            navigationPropertySegment.Identifier.Should().Be(HardCodedTestModel.GetPersonMyDogNavProp().Name);
        }
Exemplo n.º 15
0
            private static SelectItemInfo CreateNavigationSelectItemInfo(IEdmModel model, NavigationPropertySegment segment, bool propertySelect, bool?countOption)
            {
                IEdmNavigationProperty navigationEdmProperty = segment.NavigationProperty;
                var collectionType = navigationEdmProperty.Type.Definition as IEdmCollectionType;

                var resourceInfo = new ODataNestedResourceInfo()
                {
                    IsCollection = collectionType != null,
                    Name         = navigationEdmProperty.Name
                };

                var entitySet = (IEdmEntitySet)segment.NavigationSource;

                if (entitySet == null)
                {
                    IEdmType entityType;
                    if (collectionType == null)
                    {
                        entityType = navigationEdmProperty.Type.Definition;
                    }
                    else
                    {
                        entityType = collectionType.ElementType.Definition;
                    }
                    foreach (IEdmEntitySet element in model.EntityContainer.EntitySets())
                    {
                        if (element.EntityType() == entityType)
                        {
                            entitySet = element;
                            break;
                        }
                    }
                }
                return(new SelectItemInfo(entitySet, navigationEdmProperty, resourceInfo, propertySelect, countOption));
            }
Exemplo n.º 16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="NavigationSegmentTemplate" /> class.
 /// </summary>
 /// <param name="segment">The navigation property segment.</param>
 public NavigationSegmentTemplate(NavigationPropertySegment segment)
 {
     Segment = segment ?? throw Error.ArgumentNull(nameof(segment));
 }
Exemplo n.º 17
0
        public void ODataUriBuilderWithEntitySet()
        {
            Uri            fullUri        = new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID&$expand=MyDog&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA");
            ODataUriParser odataUriParser = new ODataUriParser(this.GetModel(), serviceRoot, fullUri);

            odataUriParser.UrlConventions = ODataUrlConventions.Default;
            SetODataUriParserSettingsTo(this.settings, odataUriParser.Settings);
            ODataUri odataUri = odataUriParser.ParseUri();

            //verify path
            EntitySetSegment entitySet = (EntitySetSegment)odataUri.Path.FirstSegment;

            Assert.AreEqual(entitySet.EntitySet.Name, "People");
            Assert.AreEqual(odataUri.Path.Count, 1);

            //verify $filter
            BinaryOperatorNode            binaryOperator      = (BinaryOperatorNode)odataUri.Filter.Expression;
            SingleValuePropertyAccessNode singleValueProperty = (SingleValuePropertyAccessNode)binaryOperator.Left;
            SingleNavigationNode          singleNavigation    = (SingleNavigationNode)singleValueProperty.Source;
            ConstantNode constantNode = (ConstantNode)binaryOperator.Right;

            Assert.AreEqual(binaryOperator.OperatorKind, BinaryOperatorKind.Equal);
            Assert.AreEqual(singleValueProperty.Property.Name, "Color");
            Assert.AreEqual(singleNavigation.NavigationProperty.Name, "MyDog");
            Assert.AreEqual(constantNode.LiteralText, "'Brown'");

            //verify $select and $expand
            IEnumerable <SelectItem> selectItems = odataUri.SelectAndExpand.SelectedItems;

            foreach (ExpandedNavigationSelectItem selectItem in selectItems)
            {
                NavigationPropertySegment navigationProperty = (NavigationPropertySegment)selectItem.PathToNavigationProperty.FirstSegment;
                Assert.AreEqual(navigationProperty.NavigationProperty.Name, "MyDog");
                break;
            }

            //verify $orderby
            SingleValuePropertyAccessNode orderby = (SingleValuePropertyAccessNode)odataUri.OrderBy.Expression;

            Assert.AreEqual(orderby.Property.Name, "ID");

            //verify $top
            Assert.AreEqual(odataUri.Top, 1);

            //verify $skip
            Assert.AreEqual(odataUri.Skip, 2);

            //verify $count
            Assert.AreEqual(odataUri.QueryCount, true);

            //verify $search
            SearchTermNode searchTermNode = (SearchTermNode)odataUri.Search.Expression;

            Assert.AreEqual(searchTermNode.Text, "FA");

            ODataUriBuilder odataUriBuilder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri);
            Uri             actualUri       = odataUriBuilder.BuildUri();

            Assert.AreEqual(new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyDog&$expand=MyDog&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);

            ODataUriBuilder uriBuilderWithKeyAsSegment = new ODataUriBuilder(ODataUrlConventions.KeyAsSegment, odataUri);

            actualUri = uriBuilderWithKeyAsSegment.BuildUri();
            Assert.AreEqual(new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyDog&$expand=MyDog&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);
        }
Exemplo n.º 18
0
        public OeQueryContext CreateQueryContext(ODataUri odataUri, int pageSize, bool navigationNextLink, OeMetadataLevel metadataLevel)
        {
            List <OeParseNavigationSegment> navigationSegments = null;

            if (odataUri.Path.LastSegment is KeySegment ||
                odataUri.Path.LastSegment is NavigationPropertySegment)
            {
                navigationSegments = new List <OeParseNavigationSegment>();
                ODataPathSegment previousSegment = null;
                foreach (ODataPathSegment segment in odataUri.Path)
                {
                    if (segment is NavigationPropertySegment)
                    {
                        var navigationSegment = segment as NavigationPropertySegment;
                        if (navigationSegment == odataUri.Path.LastSegment)
                        {
                            navigationSegments.Add(new OeParseNavigationSegment(navigationSegment, null));
                        }
                        else
                        {
                            navigationSegments.Add(new OeParseNavigationSegment(navigationSegment, null));
                        }
                    }
                    else if (segment is KeySegment)
                    {
                        IEdmEntitySet             previousEntitySet;
                        var                       keySegment        = segment as KeySegment;
                        NavigationPropertySegment navigationSegment = null;
                        if (previousSegment is EntitySetSegment)
                        {
                            var previousEntitySetSegment = previousSegment as EntitySetSegment;
                            previousEntitySet = previousEntitySetSegment.EntitySet;
                        }
                        else if (previousSegment is NavigationPropertySegment)
                        {
                            navigationSegment = previousSegment as NavigationPropertySegment;
                            previousEntitySet = (IEdmEntitySet)navigationSegment.NavigationSource;
                        }
                        else
                        {
                            throw new InvalidOperationException("invalid segment");
                        }

                        FilterClause keyFilter = CreateFilterClause(previousEntitySet, keySegment.Keys);
                        navigationSegments.Add(new OeParseNavigationSegment(navigationSegment, keyFilter));
                    }
                    previousSegment = segment;
                }
            }

            if (pageSize > 0)
            {
                odataUri.Top = pageSize;
                IEdmEntityType edmEntityType = GetEntityType(odataUri.Path, navigationSegments);
                odataUri.OrderBy = OeSkipTokenParser.GetUniqueOrderBy(_edmModel, edmEntityType, odataUri.OrderBy, odataUri.Apply);
            }

            var           entitySetSegment = (EntitySetSegment)odataUri.Path.FirstSegment;
            IEdmEntitySet entitySet        = entitySetSegment.EntitySet;

            Db.OeEntitySetAdapter entitySetAdapter = _dataAdapter.EntitySetAdapters.FindByEntitySetName(entitySet.Name);
            bool isCountSegment = odataUri.Path.LastSegment is CountSegment;

            return(new OeQueryContext(_edmModel, odataUri, entitySet, navigationSegments,
                                      isCountSegment, pageSize, navigationNextLink, _dataAdapter.IsDatabaseNullHighestValue, metadataLevel, entitySetAdapter));
        }
        public void Translate_NavigationPropertySegment_To_NavigationPathSegment_Works()
        {
            // Arrange
            IEdmEntitySet entityset = _model.FindDeclaredEntitySet("Products");
            IEdmEntityType entityType = _model.FindDeclaredType("System.Web.OData.Routing.RoutingCustomer") as IEdmEntityType;
            IEdmNavigationProperty navigationProperty = entityType.NavigationProperties().First(e => e.Name == "Products");
            NavigationPropertySegment segment = new NavigationPropertySegment(navigationProperty, entityset);

            // Act
            IEnumerable<ODataPathSegment> segments = _translator.Translate(segment);

            // Assert
            ODataPathSegment pathSegment = Assert.Single(segments);
            NavigationPathSegment navigationPathSegment = Assert.IsType<NavigationPathSegment>(pathSegment);
            Assert.Same(navigationProperty, navigationPathSegment.NavigationProperty);
        }
Exemplo n.º 20
0
 /// <summary>
 /// Translate a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">the segment to Translate</param>
 /// <returns>Translated odata path segment.</returns>
 public override ODataPathSegment Translate(NavigationPropertySegment segment)
 {
     return(segment);
 }
Exemplo n.º 21
0
 /// <summary>
 /// Translate a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">the segment to Translate</param>
 /// <returns>Translated the path segment template.</returns>
 public override ODataSegmentTemplate Translate(NavigationPropertySegment segment)
 {
     return(new NavigationSegmentTemplate(segment));
 }
Exemplo n.º 22
0
        public override void Handle(NavigationPropertySegment segment)
        {
            this.ThrowIfResolved();

            this.NavigationSource = segment.NavigationSource;
            this.Property = null;
            this.Type = segment.EdmType;
            this.ElementType = this.GetElementType(this.Type);

            this.PushParentSegment();
            this.childSegments.Add(segment);

            this.canonicalSegments.Add(segment);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Get the redundant type cast segment for the given navigation property segment.
        /// </summary>
        /// <param name="navigationPropertySegment">The navigation property segment.</param>
        /// <returns>The redundant type cast segment or null if the type cast is necessary.</returns>
        private ODataPathSegment GetRedundantTypeCast(NavigationPropertySegment navigationPropertySegment)
        {
            var previousSegment = this.GetPreviousSegment(navigationPropertySegment);
            if (previousSegment is TypeSegment)
            {
                var typeSegment = previousSegment;
                var entitySetSegment = this.GetPreviousSegment(typeSegment);

                IEdmEntityType owningType = entitySetSegment.EdmType as IEdmEntityType;
                if (owningType != null && owningType.FindProperty(navigationPropertySegment.NavigationProperty.Name) != null)
                {
                    // Return redundant type cast.
                    return typeSegment;
                }
            }

            return null;
        }
Exemplo n.º 24
0
 /// <summary>
 /// Translate a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">the segment to Translate</param>
 /// <returns>UserDefinedValue</returns>
 /// <exception cref="System.ArgumentNullException">Throws if the input segment is null.</exception>
 public override bool Translate(NavigationPropertySegment segment)
 {
     ExceptionUtils.CheckArgumentNotNull(segment, "segment");
     return(segment.NavigationProperty.Type.IsCollection());
 }
 /// <summary>
 /// Translate a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">the segment to Translate</param>
 /// <returns>Defined by the implementer.</returns>
 public override string Translate(NavigationPropertySegment segment)
 {
     Debug.Assert(segment != null, "segment != null");
     return("/" + segment.NavigationProperty.Name);
 }
Exemplo n.º 26
0
        /// <summary>
        /// Build the $expand item, it maybe $expand=nav, $expand=complex/nav, $expand=nav/$ref, etc.
        /// </summary>
        /// <param name="expandReferenceItem">The expanded reference select item.</param>
        /// <param name="currentLevelPropertiesInclude">The current properties to include at current level.</param>
        /// <param name="structuralTypeInfo">The structural type properties.</param>
        private void BuildExpandItem(ExpandedReferenceSelectItem expandReferenceItem,
                                     IDictionary <IEdmStructuralProperty, SelectExpandIncludedProperty> currentLevelPropertiesInclude,
                                     EdmStructuralTypeInfo structuralTypeInfo)
        {
            Contract.Assert(expandReferenceItem != null && expandReferenceItem.PathToNavigationProperty != null);
            Contract.Assert(currentLevelPropertiesInclude != null);
            Contract.Assert(structuralTypeInfo != null);

            // Verify and process the $expand=abc/xyz/nav.
            ODataExpandPath          expandPath = expandReferenceItem.PathToNavigationProperty;
            IList <ODataPathSegment> remainingSegments;
            ODataPathSegment         segment = expandPath.GetFirstNonTypeCastSegment(out remainingSegments);

            PropertySegment firstPropertySegment = segment as PropertySegment;

            if (firstPropertySegment != null)
            {
                // for example: $expand=abc/xyz/nav, the remaining segment can't be null
                // because at least the last navigation property segment is there.
                Contract.Assert(remainingSegments != null);

                if (structuralTypeInfo.IsStructuralPropertyDefined(firstPropertySegment.Property))
                {
                    SelectExpandIncludedProperty newPropertySelectItem;
                    if (!currentLevelPropertiesInclude.TryGetValue(firstPropertySegment.Property, out newPropertySelectItem))
                    {
                        newPropertySelectItem = new SelectExpandIncludedProperty(firstPropertySegment);
                        currentLevelPropertiesInclude[firstPropertySegment.Property] = newPropertySelectItem;
                    }

                    newPropertySelectItem.AddSubExpandItem(remainingSegments, expandReferenceItem);
                }
            }
            else
            {
                // for example: $expand=nav, or $expand=NS.SubType/nav, the navigation property segment should be the last segment.
                // So, the remaining segments should be null.
                Contract.Assert(remainingSegments == null);

                NavigationPropertySegment firstNavigationSegment = segment as NavigationPropertySegment;
                Contract.Assert(firstNavigationSegment != null);

                if (structuralTypeInfo.IsNavigationPropertyDefined(firstNavigationSegment.NavigationProperty))
                {
                    // It's not allowed to have mulitple navigation expanded or referenced.
                    // for example: "$expand=nav($top=2),nav($skip=3)" is not allowed and will be merged (or throw exception) at ODL side.
                    ExpandedNavigationSelectItem expanded = expandReferenceItem as ExpandedNavigationSelectItem;
                    if (expanded != null)
                    {
                        if (ExpandedProperties == null)
                        {
                            ExpandedProperties = new Dictionary <IEdmNavigationProperty, ExpandedNavigationSelectItem>();
                        }

                        ExpandedProperties[firstNavigationSegment.NavigationProperty] = expanded;
                    }
                    else
                    {
                        // $expand=..../nav/$ref
                        if (ReferencedProperties == null)
                        {
                            ReferencedProperties = new Dictionary <IEdmNavigationProperty, ExpandedReferenceSelectItem>();
                        }

                        ReferencedProperties[firstNavigationSegment.NavigationProperty] = expandReferenceItem;
                    }
                }
            }
        }
Exemplo n.º 27
0
        private void CreatePropertySegment(ODataPathSegment previous, IEdmProperty property, string queryPortion)
        {
            if (property.Type.IsStream())
            {
                // The server used to allow arbitrary key expressions after named streams because this check was missing.
                if (queryPortion != null)
                {
                    throw ExceptionUtil.CreateSyntaxError();
                }

                this.CreateNamedStreamSegment(previous, property);
                return;
            }

            // Handle a strongly-typed property.
            ODataPathSegment segment = null;

            if (property.PropertyKind == EdmPropertyKind.Navigation)
            {
                var navigationProperty = (IEdmNavigationProperty)property;
                IEdmNavigationSource navigationSource = previous.TargetEdmNavigationSource.FindNavigationTarget(navigationProperty);

                // Relationship between TargetMultiplicity and navigation property:
                //  1) EdmMultiplicity.Many <=> collection navigation property
                //  2) EdmMultiplicity.ZeroOrOne <=> nullable singleton navigation property
                //  3) EdmMultiplicity.One <=> non-nullable singleton navigation property
                //
                // According to OData Spec CSDL 7.1.3:
                //  1) non-nullable singleton navigation property => navigation source required
                //  2) the other cases => navigation source optional
                if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.One
                    && navigationSource is IEdmUnknownEntitySet)
                {
                    // Specifically not throwing ODataUriParserException since it's more an an internal server error
                    throw new ODataException(ODataErrorStrings.RequestUriProcessor_TargetEntitySetNotFound(property.Name));
                }

                segment = new NavigationPropertySegment(navigationProperty, navigationSource);
            }
            else
            {
                segment = new PropertySegment((IEdmStructuralProperty)property);
                switch (property.Type.TypeKind())
                {
                    case EdmTypeKind.Complex:
                        segment.TargetKind = RequestTargetKind.ComplexObject;
                        break;
                    case EdmTypeKind.Collection:
                        segment.TargetKind = RequestTargetKind.Collection;
                        break;
                    case EdmTypeKind.Enum:
                        segment.TargetKind = RequestTargetKind.Enum;
                        break;
                    default:
                        Debug.Assert(property.Type.IsPrimitive() || property.Type.IsTypeDefinition(), "must be primitive type or type definition property");
                        segment.TargetKind = RequestTargetKind.Primitive;
                        break;
                }
            }

            this.parsedSegments.Add(segment);

            if (!(queryPortion == null || property.Type.IsCollection() && property.Type.AsCollection().ElementType().IsEntity()))
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            this.TryBindKeyFromParentheses(queryPortion);
        }
Exemplo n.º 28
0
        /// <summary>
        /// Build the $select item, it maybe $select=complex/abc, $select=abc, $select=nav, etc.
        /// </summary>
        /// <param name="pathSelectItem">The expanded reference select item.</param>
        /// <param name="currentLevelPropertiesInclude">The current properties to include at current level.</param>
        /// <param name="structuralTypeInfo">The structural type properties.</param>
        private void BuildSelectItem(PathSelectItem pathSelectItem,
                                     IDictionary <IEdmStructuralProperty, SelectExpandIncludedProperty> currentLevelPropertiesInclude,
                                     EdmStructuralTypeInfo structuralTypeInfo)
        {
            Contract.Assert(pathSelectItem != null && pathSelectItem.SelectedPath != null);
            Contract.Assert(currentLevelPropertiesInclude != null);
            Contract.Assert(structuralTypeInfo != null);

            // Verify and process the $select=abc/xyz/....
            ODataSelectPath          selectPath = pathSelectItem.SelectedPath;
            IList <ODataPathSegment> remainingSegments;
            ODataPathSegment         segment = selectPath.GetFirstNonTypeCastSegment(out remainingSegments);

            PropertySegment firstPropertySegment = segment as PropertySegment;

            if (firstPropertySegment != null)
            {
                if (structuralTypeInfo.IsStructuralPropertyDefined(firstPropertySegment.Property))
                {
                    // $select=abc/xyz/...
                    SelectExpandIncludedProperty newPropertySelectItem;
                    if (!currentLevelPropertiesInclude.TryGetValue(firstPropertySegment.Property, out newPropertySelectItem))
                    {
                        newPropertySelectItem = new SelectExpandIncludedProperty(firstPropertySegment);
                        currentLevelPropertiesInclude[firstPropertySegment.Property] = newPropertySelectItem;
                    }

                    newPropertySelectItem.AddSubSelectItem(remainingSegments, pathSelectItem);
                }

                return;
            }

            // If the first segment is not a property segment,
            // that segment must be the last segment, so the remainging segments should be null.
            Contract.Assert(remainingSegments == null);

            NavigationPropertySegment navigationSegment = segment as NavigationPropertySegment;

            if (navigationSegment != null)
            {
                // for example: $select=NavigationProperty or $select=NS.VipCustomer/VipNav
                if (structuralTypeInfo.IsNavigationPropertyDefined(navigationSegment.NavigationProperty))
                {
                    if (SelectedNavigationProperties == null)
                    {
                        SelectedNavigationProperties = new HashSet <IEdmNavigationProperty>();
                    }

                    SelectedNavigationProperties.Add(navigationSegment.NavigationProperty);
                }

                return;
            }

            OperationSegment operationSegment = segment as OperationSegment;

            if (operationSegment != null)
            {
                // for example: $select=NS.Operation, or, $select=NS.VipCustomer/NS.Operation
                AddOperations(operationSegment, structuralTypeInfo.AllActions, structuralTypeInfo.AllFunctions);
                return;
            }

            DynamicPathSegment dynamicPathSegment = segment as DynamicPathSegment;

            if (dynamicPathSegment != null)
            {
                if (SelectedDynamicProperties == null)
                {
                    SelectedDynamicProperties = new HashSet <string>();
                }

                SelectedDynamicProperties.Add(dynamicPathSegment.Identifier);
                return;
            }

            // In fact, we should never be here, because it's verified above
            throw new ODataException(Error.Format(SRResources.SelectionTypeNotSupported, segment.GetType().Name));
        }
Exemplo n.º 29
0
        public void ODataUriBuilderWithEntitySet()
        {
            Uri            fullUri        = new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID&$expand=MyDog%2CMyCat/$ref&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA");
            ODataUriParser odataUriParser = new ODataUriParser(this.GetModel(), serviceRoot, fullUri);

            odataUriParser.UrlKeyDelimiter = ODataUrlKeyDelimiter.Parentheses;
            SetODataUriParserSettingsTo(this.settings, odataUriParser.Settings);
            ODataUri odataUri = odataUriParser.ParseUri();

            //verify path
            EntitySetSegment entitySet = (EntitySetSegment)odataUri.Path.FirstSegment;

            Assert.Equal(entitySet.EntitySet.Name, "People");
            Assert.Equal(odataUri.Path.Count, 1);

            //verify $filter
            BinaryOperatorNode            binaryOperator      = (BinaryOperatorNode)odataUri.Filter.Expression;
            SingleValuePropertyAccessNode singleValueProperty = (SingleValuePropertyAccessNode)binaryOperator.Left;
            SingleNavigationNode          singleNavigation    = (SingleNavigationNode)singleValueProperty.Source;
            ConstantNode constantNode = (ConstantNode)binaryOperator.Right;

            Assert.Equal(binaryOperator.OperatorKind, BinaryOperatorKind.Equal);
            Assert.Equal(singleValueProperty.Property.Name, "Color");
            Assert.Equal(singleNavigation.NavigationProperty.Name, "MyDog");
            Assert.Equal(constantNode.LiteralText, "'Brown'");

            //verify $select and $expand
            IEnumerable <SelectItem> selectItems = odataUri.SelectAndExpand.SelectedItems;
            IEnumerable <ExpandedNavigationSelectItem> expandedNavigationSelectItem = selectItems.Where(I => I.GetType() == typeof(ExpandedNavigationSelectItem)).OfType <ExpandedNavigationSelectItem>();
            IEnumerable <ExpandedReferenceSelectItem>  expandedReferenceSelectItem  = selectItems.Where(I => I.GetType() == typeof(ExpandedReferenceSelectItem)).OfType <ExpandedReferenceSelectItem>();
            IEnumerable <PathSelectItem> pathSelectItem = selectItems.Where(I => I.GetType() == typeof(PathSelectItem)).OfType <PathSelectItem>();

            Assert.Equal(expandedNavigationSelectItem.Count(), 1);
            Assert.Equal(expandedReferenceSelectItem.Count(), 1);
            Assert.Equal(pathSelectItem.Count(), 2);
            NavigationPropertySegment navigationProperty = (NavigationPropertySegment)expandedNavigationSelectItem.First().PathToNavigationProperty.FirstSegment;

            Assert.Equal(navigationProperty.NavigationProperty.Name, "MyDog");
            navigationProperty = (NavigationPropertySegment)expandedReferenceSelectItem.First().PathToNavigationProperty.FirstSegment;
            Assert.Equal(navigationProperty.NavigationProperty.Name, "MyCat");

            //verify $orderby
            SingleValuePropertyAccessNode orderby = (SingleValuePropertyAccessNode)odataUri.OrderBy.Expression;

            Assert.Equal(orderby.Property.Name, "ID");

            //verify $top
            Assert.Equal(odataUri.Top, 1);

            //verify $skip
            Assert.Equal(odataUri.Skip, 2);

            //verify $count
            Assert.Equal(odataUri.QueryCount, true);

            //verify $search
            SearchTermNode searchTermNode = (SearchTermNode)odataUri.Search.Expression;

            Assert.Equal(searchTermNode.Text, "FA");

            Uri actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Parentheses);

            Assert.Equal(new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);

            actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Slash);
            Assert.Equal(new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);
        }
Exemplo n.º 30
0
 /// <summary>
 /// Translate a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">the segment to Translate</param>
 /// <returns>Defined by the implementer.</returns>
 public override string Translate(NavigationPropertySegment segment)
 {
     return("/" + segment.NavigationProperty.Name);
 }
 /// <summary>
 /// Handle a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">the segment to Handle</param>
 public override void Handle(NavigationPropertySegment segment)
 {
     CommonHandler(segment);
 }
 public OeParseNavigationSegment(NavigationPropertySegment navigationSegment, FilterClause filter)
 {
     NavigationSegment = navigationSegment;
     Filter            = filter;
 }
Exemplo n.º 33
0
 /// <summary>
 /// Handle validating a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">The navigation property segment to valdiate.</param>
 public override void Handle(NavigationPropertySegment segment)
 {
     ValidateItemAndType(segment);
     ValidateItem(segment.NavigationProperty);
     ValidateItem(segment.NavigationSource);
 }
Exemplo n.º 34
0
        /// <inheritdoc/>
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }

            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }

            if (actionMap == null)
            {
                throw Error.ArgumentNull("actionMap");
            }

            HttpMethod method           = controllerContext.Request.Method;
            string     actionNamePrefix = GetActionMethodPrefix(method);

            if (actionNamePrefix == null)
            {
                return(null);
            }

            if (odataPath.PathTemplate == "~/entityset/key/navigation" ||
                odataPath.PathTemplate == "~/entityset/key/navigation/$count" ||
                odataPath.PathTemplate == "~/entityset/key/cast/navigation" ||
                odataPath.PathTemplate == "~/entityset/key/cast/navigation/$count" ||
                odataPath.PathTemplate == "~/singleton/navigation" ||
                odataPath.PathTemplate == "~/singleton/navigation/$count" ||
                odataPath.PathTemplate == "~/singleton/cast/navigation" ||
                odataPath.PathTemplate == "~/singleton/cast/navigation/$count")
            {
                NavigationPropertySegment navigationSegment =
                    (odataPath.Segments.Last() as NavigationPropertySegment) ??
                    odataPath.Segments[odataPath.Segments.Count - 2] as NavigationPropertySegment;
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

                // It is not valid to *Post* to any non-collection valued navigation property.
                if (navigationProperty.TargetMultiplicity() != EdmMultiplicity.Many &&
                    method == HttpMethod.Post)
                {
                    return(null);
                }

                // It is not valid to *Put/Patch" to any collection-valued navigation property.
                if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many &&
                    (method == HttpMethod.Put || "PATCH" == method.Method.ToUpperInvariant()))
                {
                    return(null);
                }

                // *Get* is the only supported method for $count request.
                if (odataPath.Segments.Last() is CountSegment && method != HttpMethod.Get)
                {
                    return(null);
                }

                if (declaringType != null)
                {
                    // e.g. Try GetNavigationPropertyFromDeclaringType first, then fallback on GetNavigationProperty action name
                    string actionName = actionMap.FindMatchingAction(
                        actionNamePrefix + navigationProperty.Name + "From" + declaringType.Name,
                        actionNamePrefix + navigationProperty.Name);

                    if (actionName != null)
                    {
                        if (odataPath.PathTemplate.StartsWith("~/entityset/key", StringComparison.Ordinal))
                        {
                            KeySegment keyValueSegment = (KeySegment)odataPath.Segments[1];
                            controllerContext.AddKeyValueToRouteData(keyValueSegment);
                        }

                        return(actionName);
                    }
                }
            }

            return(null);
        }
Exemplo n.º 35
0
 /// <summary>
 /// Handle a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">the segment to Handle</param>
 public virtual void Handle(NavigationPropertySegment segment)
 {
     throw new NotImplementedException();
 }
 public void TargetKindShouldBeResource()
 {
     NavigationPropertySegment navigationPropertySegment = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);
     navigationPropertySegment.TargetKind.Should().Be(RequestTargetKind.Resource);
 }
 public void IdentifierShouldBeNavPropName()
 {
     NavigationPropertySegment navigationPropertySegment = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);
     navigationPropertySegment.Identifier.Should().Be(HardCodedTestModel.GetPersonMyDogNavProp().Name);
 }
 public void EqualityIsCorrect()
 {
     NavigationPropertySegment navigationPropertySegment1 = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);
     NavigationPropertySegment navigationPropertySegment2 = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);
     navigationPropertySegment1.Equals(navigationPropertySegment2).Should().BeTrue();
 }
Exemplo n.º 39
0
 /// <summary>
 /// Translate a NavigationPropertySegment
 /// </summary>
 /// <param name="segment">the segment to Translate</param>
 /// <returns>Translated WebApi path segment.</returns>
 public override IEnumerable <ODataPathSegment> Translate(NavigationPropertySegment segment)
 {
     yield return(new NavigationPathSegment(segment.NavigationProperty));
 }
Exemplo n.º 40
0
        // Determines if a status code needs to be changed based on the path of the request and returns the new
        // status code or null if no change is required.
        internal static HttpStatusCode?GetUpdatedResponseStatusCodeOrNull(ODataPath oDataPath)
        {
            if (oDataPath == null || oDataPath.Segments == null || oDataPath.Segments.Count == 0)
            {
                return(null);
            }

            // Skip any sequence of cast segments at the end of the path.
            int currentIndex = oDataPath.Segments.Count - 1;
            ReadOnlyCollection <ODataPathSegment> segments = oDataPath.Segments;

            while (currentIndex >= 0 && segments[currentIndex] is TypeSegment)
            {
                currentIndex--;
            }

            // Null value properties should be treated in the same way independent of whether the user asked for the
            // raw value of the property or a specific format, so we skip the $value segment as it can only be
            // preceded by a property access segment.
            if (currentIndex >= 0 && segments[currentIndex] is ValueSegment)
            {
                currentIndex--;
            }

            // Protect ourselves against malformed path segments.
            if (currentIndex < 0)
            {
                return(null);
            }

            KeySegment keySegment = segments[currentIndex] as KeySegment;

            if (keySegment != null)
            {
                // Look at the previous segment to decide, but skip any possible sequence of cast segments in
                // between.
                currentIndex--;
                while (currentIndex >= 0 && segments[currentIndex] is TypeSegment)
                {
                    currentIndex--;
                }
                if (currentIndex < 0)
                {
                    return(null);
                }

                if (segments[currentIndex] is EntitySetSegment)
                {
                    // Return 404 if we were trying to retrieve a specific entity from an entity set.
                    return(HttpStatusCode.NotFound);
                }

                if (segments[currentIndex] is NavigationPropertySegment)
                {
                    // Return 204 if we were trying to retrieve a related entity via a navigation property.
                    return(HttpStatusCode.NoContent);
                }

                return(null);
            }

            PropertySegment propertySegment = segments[currentIndex] as PropertySegment;

            if (propertySegment != null)
            {
                // Return 204 only if the property is single valued (not a collection of values).
                return(GetChangedStatusCodeForProperty(propertySegment));
            }

            NavigationPropertySegment navigationSegment = segments[currentIndex] as NavigationPropertySegment;

            if (navigationSegment != null)
            {
                // Return 204 only if the navigation property is a single related entity and not a collection
                // of entities.
                return(GetChangedStatusCodeForNavigationProperty(navigationSegment));
            }

            SingletonSegment singletonSegment = segments[currentIndex] as SingletonSegment;

            if (singletonSegment != null)
            {
                // Return 404 for a singleton with a null value.
                return(HttpStatusCode.NotFound);
            }

            return(null);
        }
 public void NavPropSetCorrectly()
 {
     NavigationPropertySegment segment = new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null);
     segment.NavigationProperty.Should().BeSameAs(HardCodedTestModel.GetPersonMyDogNavProp());
 }
        /// <inheritdoc/>
        public override ActionDescriptor SelectAction(RouteContext routeContext, IEnumerable <ControllerActionDescriptor> actionDescriptors)
        {
            if (routeContext == null)
            {
                throw Error.ArgumentNull("routeContext");
            }

            ODataPath   odataPath  = routeContext.HttpContext.Request.ODataFeature().Path;
            HttpRequest request    = routeContext.HttpContext.Request;
            string      httpMethod = request.Method.ToUpperInvariant();

            string actionNamePrefix = GetActionMethodPrefix(httpMethod);

            if (actionNamePrefix == null)
            {
                return(null);
            }

            if (odataPath.PathTemplate == "~/entityset/key/navigation" ||
                odataPath.PathTemplate == "~/entityset/key/navigation/$count" ||
                odataPath.PathTemplate == "~/entityset/key/cast/navigation" ||
                odataPath.PathTemplate == "~/entityset/key/cast/navigation/$count" ||
                odataPath.PathTemplate == "~/singleton/navigation" ||
                odataPath.PathTemplate == "~/singleton/navigation/$count" ||
                odataPath.PathTemplate == "~/singleton/cast/navigation" ||
                odataPath.PathTemplate == "~/singleton/cast/navigation/$count")
            {
                NavigationPropertySegment navigationSegment =
                    (odataPath.Segments.Last() as NavigationPropertySegment) ??
                    odataPath.Segments[odataPath.Segments.Count - 2] as NavigationPropertySegment;
                IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                IEdmEntityType         declaringType      = navigationProperty.DeclaringType as IEdmEntityType;

                // It is not valid to *Post* to any non-collection valued navigation property.
                if (navigationProperty.TargetMultiplicity() != EdmMultiplicity.Many &&
                    httpMethod == ODataRouteConstants.HttpPost)
                {
                    return(null);
                }

                // It is not valid to *Put/Patch" to any collection-valued navigation property.
                if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many &&
                    (httpMethod == ODataRouteConstants.HttpPut || httpMethod == ODataRouteConstants.HttpPatch))
                {
                    return(null);
                }

                // *Get* is the only supported method for $count request.
                if (odataPath.Segments.Last() is CountSegment && httpMethod != ODataRouteConstants.HttpGet)
                {
                    return(null);
                }

                if (declaringType != null)
                {
                    // e.g. Try GetNavigationPropertyFromDeclaringType first, then fallback on GetNavigationProperty action name
                    ControllerActionDescriptor actionDescriptor = actionDescriptors.FindMatchingAction(
                        actionNamePrefix + navigationProperty.Name + "From" + declaringType.Name,
                        actionNamePrefix + navigationProperty.Name,
                        navigationProperty.Name);

                    if (actionDescriptor != null)
                    {
                        if (odataPath.PathTemplate.StartsWith("~/entityset/key", StringComparison.Ordinal))
                        {
                            KeySegment keyValueSegment = (KeySegment)odataPath.Segments[1];
                            routeContext.AddKeyValueToRouteData(keyValueSegment, actionDescriptor);
                        }

                        return(actionDescriptor);
                    }
                }
            }

            return(null);
        }
Exemplo n.º 43
0
        private void ValidateRestrictions(
            int?remainDepth,
            int currentDepth,
            SelectExpandClause selectExpandClause,
            IEdmNavigationProperty navigationProperty,
            ODataValidationSettings validationSettings)
        {
            IEdmModel edmModel = _selectExpandQueryOption.Context.Model;
            int?      depth    = remainDepth;

            if (remainDepth < 0)
            {
                throw new ODataException(
                          Error.Format(SRResources.MaxExpandDepthExceeded, currentDepth - 1, "MaxExpansionDepth"));
            }

            IEdmProperty       pathProperty;
            IEdmStructuredType pathStructuredType;

            if (navigationProperty == null)
            {
                pathProperty       = _selectExpandQueryOption.Context.TargetProperty;
                pathStructuredType = _selectExpandQueryOption.Context.TargetStructuredType;
            }
            else
            {
                pathProperty       = navigationProperty;
                pathStructuredType = navigationProperty.ToEntityType();
            }

            foreach (SelectItem selectItem in selectExpandClause.SelectedItems)
            {
                ExpandedNavigationSelectItem expandItem = selectItem as ExpandedNavigationSelectItem;
                if (expandItem != null)
                {
                    NavigationPropertySegment navigationSegment =
                        (NavigationPropertySegment)expandItem.PathToNavigationProperty.LastSegment;
                    IEdmNavigationProperty property = navigationSegment.NavigationProperty;
                    if (EdmHelpers.IsNotExpandable(property, edmModel))
                    {
                        throw new ODataException(Error.Format(SRResources.NotExpandablePropertyUsedInExpand,
                                                              property.Name));
                    }

                    if (edmModel != null)
                    {
                        ValidateOtherQueryOptionInExpand(property, edmModel, expandItem, validationSettings);
                        bool isExpandable;
                        ExpandConfiguration expandConfiguration;
                        isExpandable = EdmHelpers.IsExpandable(property.Name,
                                                               pathProperty,
                                                               pathStructuredType,
                                                               edmModel,
                                                               out expandConfiguration);
                        if (isExpandable)
                        {
                            int maxDepth = expandConfiguration.MaxDepth;
                            if (maxDepth > 0 && (remainDepth == null || maxDepth < remainDepth))
                            {
                                remainDepth = maxDepth;
                            }
                        }
                        else if (!isExpandable)
                        {
                            if (!_defaultQuerySettings.EnableExpand ||
                                (expandConfiguration != null && expandConfiguration.ExpandType == SelectExpandType.Disabled))
                            {
                                throw new ODataException(Error.Format(SRResources.NotExpandablePropertyUsedInExpand,
                                                                      property.Name));
                            }
                        }
                    }

                    if (remainDepth.HasValue)
                    {
                        remainDepth--;
                        if (expandItem.LevelsOption != null)
                        {
                            ValidateLevelsOption(expandItem.LevelsOption, remainDepth.Value, currentDepth + 1, edmModel,
                                                 property);
                        }
                    }

                    ValidateRestrictions(remainDepth, currentDepth + 1, expandItem.SelectAndExpand, property,
                                         validationSettings);
                    remainDepth = depth;
                }

                ValidateSelectItem(selectItem, pathProperty, pathStructuredType, edmModel);
            }
        }
Exemplo n.º 44
0
        private void ProcessTokenAsPath(NonSystemToken tokenIn)
        {
            Debug.Assert(tokenIn != null, "tokenIn != null");

            List <ODataPathSegment> pathSoFar        = new List <ODataPathSegment>();
            IEdmStructuredType      currentLevelType = this.edmType;

            // first, walk through all type segments in a row, converting them from tokens into segments.
            if (tokenIn.IsNamespaceOrContainerQualified())
            {
                PathSegmentToken firstNonTypeToken;
                pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(tokenIn, this.model, this.maxDepth, this.resolver, ref currentLevelType, out firstNonTypeToken));
                Debug.Assert(firstNonTypeToken != null, "Did not get last token.");
                tokenIn = firstNonTypeToken as NonSystemToken;
                if (tokenIn == null)
                {
                    throw new ODataException(ODataErrorStrings.SelectPropertyVisitor_SystemTokenInSelect(firstNonTypeToken.Identifier));
                }
            }

            // next, create a segment for the first non-type segment in the path.
            ODataPathSegment lastSegment = SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(tokenIn, this.model, currentLevelType, resolver);

            // next, create an ODataPath and add the segments to it.
            if (lastSegment != null)
            {
                pathSoFar.Add(lastSegment);

                bool hasCollectionInPath = false;

                // try create a complex type property path.
                while (true)
                {
                    // no need to go on if the current property is not of complex type or collection of complex type.
                    currentLevelType = lastSegment.EdmType as IEdmStructuredType;
                    var collectionType = lastSegment.EdmType as IEdmCollectionType;
                    if ((currentLevelType == null || currentLevelType.TypeKind != EdmTypeKind.Complex) &&
                        (collectionType == null || collectionType.ElementType.TypeKind() != EdmTypeKind.Complex))
                    {
                        break;
                    }

                    NonSystemToken nextToken = tokenIn.NextToken as NonSystemToken;
                    if (nextToken == null)
                    {
                        break;
                    }

                    lastSegment = null;

                    // This means last segment a collection of complex type,
                    // current segment can only be type cast and cannot be proprty name.
                    if (currentLevelType == null)
                    {
                        currentLevelType    = collectionType.ElementType.Definition as IEdmStructuredType;
                        hasCollectionInPath = true;
                    }
                    else if (!hasCollectionInPath)
                    {
                        // If there is no collection type in the path yet, will try to bind property for the next token
                        // first try bind the segment as property.
                        lastSegment = SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(nextToken, this.model,
                                                                                                currentLevelType, resolver);
                    }

                    // then try bind the segment as type cast.
                    if (lastSegment == null)
                    {
                        IEdmStructuredType typeFromNextToken = UriEdmHelpers.FindTypeFromModel(this.model, nextToken.Identifier, this.resolver) as IEdmStructuredType;

                        if (typeFromNextToken.IsOrInheritsFrom(currentLevelType))
                        {
                            lastSegment = new TypeSegment(typeFromNextToken, /*entitySet*/ null);
                        }
                    }

                    // type cast failed too.
                    if (lastSegment == null)
                    {
                        break;
                    }

                    // try move to and add next path segment.
                    tokenIn = nextToken;
                    pathSoFar.Add(lastSegment);
                }
            }

            ODataSelectPath selectedPath = new ODataSelectPath(pathSoFar);

            var selectionItem = new PathSelectItem(selectedPath);

            // non-navigation cases do not allow further segments in $select.
            if (tokenIn.NextToken != null)
            {
                throw new ODataException(ODataErrorStrings.SelectBinder_MultiLevelPathInSelect);
            }

            // if the selected item is a nav prop, then see if its already there before we add it.
            NavigationPropertySegment trailingNavPropSegment = selectionItem.SelectedPath.LastSegment as NavigationPropertySegment;

            if (trailingNavPropSegment != null)
            {
                if (this.expandClauseToDecorate.SelectedItems.Any(x => x is PathSelectItem &&
                                                                  ((PathSelectItem)x).SelectedPath.Equals(selectedPath)))
                {
                    return;
                }
            }

            this.expandClauseToDecorate.AddToSelectedItems(selectionItem);
        }
Exemplo n.º 45
0
        private void CreatePropertySegment(ODataPathSegment previous, IEdmProperty property, string queryPortion)
        {
            if (property.Type.IsStream())
            {
                // The server used to allow arbitrary key expressions after named streams because this check was missing.
                if (queryPortion != null)
                {
                    throw ExceptionUtil.CreateSyntaxError();
                }

                this.CreateNamedStreamSegment(previous, property);
                return;
            }

            // Handle a strongly-typed property.
            ODataPathSegment segment = null;

            if (property.PropertyKind == EdmPropertyKind.Navigation)
            {
                var navigationProperty = (IEdmNavigationProperty)property;
                IEdmNavigationSource navigationSource = previous.TargetEdmNavigationSource.FindNavigationTarget(navigationProperty);

                segment = new NavigationPropertySegment(navigationProperty, navigationSource);
            }
            else
            {
                segment = new PropertySegment((IEdmStructuralProperty)property);
                switch (property.Type.TypeKind())
                {
                    case EdmTypeKind.Complex:
                        segment.TargetKind = RequestTargetKind.ComplexObject;
                        break;
                    case EdmTypeKind.Collection:
                        segment.TargetKind = RequestTargetKind.Collection;
                        break;
                    case EdmTypeKind.Enum:
                        segment.TargetKind = RequestTargetKind.Enum;
                        break;
                    default:
                        Debug.Assert(property.Type.IsPrimitive() || property.Type.IsTypeDefinition(), "must be primitive type or type definition property");
                        segment.TargetKind = RequestTargetKind.Primitive;
                        break;
                }
            }

            this.parsedSegments.Add(segment);

            if (!(queryPortion == null || property.Type.IsCollection() && property.Type.AsCollection().ElementType().IsEntity()))
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            this.TryBindKeyFromParentheses(queryPortion);
        }
Exemplo n.º 46
0
        /// <summary>
        /// Creates an instance of <see cref="SelectItem"/> to represent the selection of the given property.
        /// </summary>
        /// <param name="metadataProviderEdmModel">The metadata provider-based edm model.</param>
        /// <param name="targetResourceType">The resource type the property is being selected for.</param>
        /// <param name="property">The property being selected.</param>
        /// <param name="typeSegments">Type segments seen in the path so far.</param>
        /// <returns>A new <see cref="SelectItem"/> to represent the selection of the given property.</returns>
        private static SelectItem CreatePropertySelection(MetadataProviderEdmModel metadataProviderEdmModel, ResourceType targetResourceType, ResourceProperty property, ICollection<TypeSegment> typeSegments)
        {
            var structuredType = (IEdmStructuredType)metadataProviderEdmModel.EnsureSchemaType(targetResourceType);
            IEdmProperty edmProperty = structuredType.FindProperty(property.Name);
            var edmStructuralProperty = edmProperty as IEdmStructuralProperty;

            Segment lastSegment;
            if (edmStructuralProperty != null)
            {
                lastSegment = new PropertySegment(edmStructuralProperty);
            }
            else
            {
                lastSegment = new NavigationPropertySegment((IEdmNavigationProperty)edmProperty);
            }

            var path = CreatePath(typeSegments, lastSegment);
            return new PathSelectItem(path);
        }