Beispiel #1
0
 internal static IEdmProperty FindDefinedProperty(string propertyName, IEdmStructuredType owningStructuredType, ODataMessageReaderSettings messageReaderSettings)
 {
     if (owningStructuredType == null)
     {
         return null;
     }
     IEdmProperty property = owningStructuredType.FindProperty(propertyName);
     if (((property == null) && owningStructuredType.IsOpen) && (messageReaderSettings.UndeclaredPropertyBehaviorKinds != ODataUndeclaredPropertyBehaviorKinds.None))
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_UndeclaredPropertyBehaviorKindSpecifiedForOpenType(propertyName, owningStructuredType.ODataFullName()));
     }
     return property;
 }
        /// <summary>
        /// Build a segment from a token.
        /// </summary>
        /// <param name="tokenIn">the token to bind</param>
        /// <param name="model">The model.</param>
        /// <param name="edmType">the type of the current scope based on type segments.</param>
        /// <param name="resolver">Resolver for uri parser.</param>
        /// <returns>The segment created from the token.</returns>
        public static ODataPathSegment ConvertNonTypeTokenToSegment(PathSegmentToken tokenIn, IEdmModel model, IEdmStructuredType edmType, ODataUriResolver resolver = null)
        {
            if (resolver == null)
            {
                resolver = ODataUriResolver.Default;
            }

            ODataPathSegment nextSegment;
            if (TryBindAsDeclaredProperty(tokenIn, edmType, resolver, out nextSegment))
            {
                return nextSegment;
            }

            // Operations must be container-qualified, and because the token type indicates it was not a .-seperated identifier, we should not try to look up operations.
            if (tokenIn.IsNamespaceOrContainerQualified())
            {
                if (TryBindAsOperation(tokenIn, model, edmType, out nextSegment))
                {
                    return nextSegment;
                }

                // If an action or function is requested in a selectItem using a qualifiedActionName or a qualifiedFunctionName 
                // and that operation cannot be bound to the entities requested, the service MUST ignore the selectItem.
                if (!edmType.IsOpen)
                {
                    return null;
                }
            }

            if (edmType.IsOpen)
            {
                return new OpenPropertySegment(tokenIn.Identifier);
            }

            throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(edmType.ODataFullName(), tokenIn.Identifier));
        }
        internal static IEdmProperty FindDefinedProperty(string propertyName, IEdmStructuredType owningStructuredType, ODataMessageReaderSettings messageReaderSettings)
        {
            if (owningStructuredType == null)
            {
                return(null);
            }
            IEdmProperty property = owningStructuredType.FindProperty(propertyName);

            if (((property == null) && owningStructuredType.IsOpen) && (messageReaderSettings.UndeclaredPropertyBehaviorKinds != ODataUndeclaredPropertyBehaviorKinds.None))
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_UndeclaredPropertyBehaviorKindSpecifiedForOpenType(propertyName, owningStructuredType.ODataFullName()));
            }
            return(property);
        }
        private static void VerifyComplexType(IEdmTypeReference expectedTypeReference, IEdmType payloadType, bool failIfNotRelated)
        {
            IEdmStructuredType thisType  = expectedTypeReference.AsStructured().StructuredDefinition();
            IEdmStructuredType otherType = (IEdmStructuredType)payloadType;

            if (!thisType.IsEquivalentTo(otherType))
            {
                if (thisType.IsAssignableFrom(otherType))
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_DerivedComplexTypesAreNotAllowed(thisType.ODataFullName(), otherType.ODataFullName()));
                }
                if (failIfNotRelated)
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_IncompatibleType(otherType.ODataFullName(), thisType.ODataFullName()));
                }
            }
        }
        internal static IEdmProperty ValidateValuePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType, ODataMessageReaderSettings messageReaderSettings, out bool ignoreProperty)
        {
            ignoreProperty = false;
            if (owningStructuredType == null)
            {
                return(null);
            }
            IEdmProperty property = FindDefinedProperty(propertyName, owningStructuredType, messageReaderSettings);

            if ((property == null) && !owningStructuredType.IsOpen)
            {
                if (!messageReaderSettings.UndeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty))
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
                }
                ignoreProperty = true;
            }
            return(property);
        }
        /// <summary>
        /// Gets the property info for the EDM property declared on this type.
        /// </summary>
        /// <param name="structuredType">The structured type to get the property on.</param>
        /// <param name="property">Property instance to get the property info for.</param>
        /// <param name="model">The model containing annotations.</param>
        /// <returns>Returns the PropertyInfo object for the specified EDM property.</returns>
        internal PropertyInfo GetPropertyInfo(IEdmStructuredType structuredType, IEdmProperty property, IEdmModel model)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(structuredType != null, "structuredType != null");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(model != null, "model != null");
            Debug.Assert(property.GetCanReflectOnInstanceTypeProperty(model), "property.CanReflectOnInstanceTypeProperty()");
#if DEBUG
            Debug.Assert(structuredType.ContainsProperty(property), "The structuredType does not define the specified property.");
#endif

            if (this.propertyInfosDeclaredOnThisType == null)
            {
                this.propertyInfosDeclaredOnThisType = new Dictionary<IEdmProperty, PropertyInfo>(ReferenceEqualityComparer<IEdmProperty>.Instance);
            }

            PropertyInfo propertyInfo;
            if (!this.propertyInfosDeclaredOnThisType.TryGetValue(property, out propertyInfo))
            {
                BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;
                propertyInfo = structuredType.GetInstanceType(model).GetProperty(property.Name, bindingFlags);
                if (propertyInfo == null)
                {
                    throw new ODataException(Strings.PropertyInfoTypeAnnotation_CannotFindProperty(structuredType.ODataFullName(), structuredType.GetInstanceType(model), property.Name));
                }

                this.propertyInfosDeclaredOnThisType.Add(property, propertyInfo);
            }

            Debug.Assert(propertyInfo != null, "propertyInfo != null");
            return propertyInfo;
        }
Beispiel #7
0
        /// <summary>
        /// Validates that a property with the specified name exists on a given structured type.
        /// The structured type can be null if no metadata is available.
        /// </summary>
        /// <param name="propertyName">The name of the property to validate.</param>
        /// <param name="owningStructuredType">The owning type of the property with name <paramref name="propertyName"/>
        /// or null if no metadata is available.</param>
        /// <param name="undeclaredPropertyBehaviorKinds">Value of UndeclaredPropertyBehaviorKinds in message settings.</param>
        /// <returns>The <see cref="IEdmProperty"/> instance representing the property with name <paramref name="propertyName"/>
        /// or null if no metadata is available.</returns>
        internal static IEdmProperty ValidatePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType, ODataUndeclaredPropertyBehaviorKinds undeclaredPropertyBehaviorKinds)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");

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

            // .None / .LinkProperty
            bool throwErr = !undeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty) &&
                            !undeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.SupportUndeclaredValueProperty);

            IEdmProperty property = owningStructuredType.FindProperty(propertyName);

            // verify that the property is declared if the type is not an open type.
            if (throwErr && !owningStructuredType.IsOpen && property == null)
            {
                throw new ODataException(Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
            }

            return(property);
        }
Beispiel #8
0
        /// <summary>
        /// Resolve property from property name
        /// </summary>
        /// <param name="type">The declaring type.</param>
        /// <param name="propertyName">The property name.</param>
        /// <returns>The resolved <see cref="IEdmProperty"/></returns>
        public virtual IEdmProperty ResolveProperty(IEdmStructuredType type, string propertyName)
        {
            if (EnableCaseInsensitive)
            {
                var result = type.Properties()
                             .Where(_ => string.Equals(propertyName, _.Name, StringComparison.OrdinalIgnoreCase))
                             .ToList();

                if (result.Count == 1)
                {
                    return(result.Single());
                }
                else if (result.Count > 1)
                {
                    throw new ODataException(Strings.UriParserMetadata_MultiplePropertiesFound(propertyName, type.ODataFullName()));
                }
            }

            return(type.FindProperty(propertyName));
        }
        /// <summary>
        /// Validates that a property with the specified name exists on a given structured type.
        /// The structured type can be null if no metadata is available.
        /// </summary>
        /// <param name="propertyName">The name of the property to validate.</param>
        /// <param name="owningStructuredType">The owning type of the property with name <paramref name="propertyName"/> 
        /// or null if no metadata is available.</param>
        /// <param name="messageReaderSettings">The message reader settings being used.</param>
        /// <returns>The <see cref="IEdmProperty"/> instance representing the property with name <paramref name="propertyName"/> 
        /// or null if no metadata is available.</returns>
        internal static IEdmProperty ValidateLinkPropertyDefined(string propertyName, IEdmStructuredType owningStructuredType, ODataMessageReaderSettings messageReaderSettings)
        {
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");
            Debug.Assert(messageReaderSettings != null, "messageReaderSettings != null");

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

            IEdmProperty property = FindDefinedProperty(propertyName, owningStructuredType);
            if (property == null && !owningStructuredType.IsOpen)
            {
                if (!messageReaderSettings.ReportUndeclaredLinkProperties)
                {
                    throw new ODataException(Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
                }
            }

            return property;
        }
        /// <summary>
        /// Should write property or not.
        /// </summary>
        /// <param name="owningType">The IEdmStructuredType</param>
        /// <param name="property">The ODataProperty to be written.</param>
        /// <param name="edmProperty">The found edm information in model.</param>
        /// <param name="shouldWriteRawAnnotations">Outputs if should write raw annotations.</param>
        /// <returns>True if should write property.</returns>
        private bool ShouldWriteProperty(IEdmStructuredType owningType, ODataProperty property, IEdmProperty edmProperty, out bool shouldWriteRawAnnotations)
        {
            shouldWriteRawAnnotations = false;
            if (owningType == null)
            {
                return(true); // for top level property
            }

            if (edmProperty != null)
            {
                return(true); // has declared property name
            }

            // for undeclared property name:
            string propertyName = property.Name;

            if (owningType.IsOpen)
            {
                // when value type is known, return true;
                ODataComplexValue complexVal = property.Value as ODataComplexValue;
                if (complexVal != null && !string.IsNullOrEmpty(complexVal.TypeName))
                {
                    return(true);
                }

                ODataCollectionValue collectionVal = property.Value as ODataCollectionValue;
                if (collectionVal != null && !string.IsNullOrEmpty(collectionVal.TypeName))
                {
                    return(true);
                }

                if (!(property.Value is ODataUntypedValue))
                {
                    return(true);
                }
            }

            // for non-open owning type, or for open owning type where value type is unknown, like ODataUntypedValue.
            if (this.MessageWriterSettings.ContainUndeclaredPropertyBehavior(
                    ODataUndeclaredPropertyBehaviorKinds.SupportUndeclaredValueProperty))
            {
                shouldWriteRawAnnotations = true;
                return(true);
            }

            if (this.MessageWriterSettings.ContainUndeclaredPropertyBehavior(
                    ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty))
            {
                return(false);
            }

            throw new ODataException(ODataErrorStrings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningType.ODataFullName()));
        }
Beispiel #11
0
 internal static IEdmProperty ValidatePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType)
 {
     if (owningStructuredType == null)
     {
         return null;
     }
     IEdmProperty property = owningStructuredType.FindProperty(propertyName);
     if (!owningStructuredType.IsOpen && (property == null))
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
     }
     return property;
 }
        /// <summary>
        /// Validates that a property with the specified name exists on a given structured type.
        /// The structured type can be null if no metadata is available.
        /// </summary>
        /// <param name="propertyName">The name of the property to validate.</param>
        /// <param name="owningStructuredType">The owning type of the property with name <paramref name="propertyName"/> 
        /// or null if no metadata is available.</param>
        /// <param name="messageReaderSettings">The message reader settings being used.</param>
        /// <param name="ignoreProperty">true if the property should be completely ignored and not parsed/reported, in this case the return value is null.
        /// false if the property should be parsed and reported as usual.</param>
        /// <returns>The <see cref="IEdmProperty"/> instance representing the property with name <paramref name="propertyName"/> 
        /// or null if no metadata is available.</returns>
        internal static IEdmProperty ValidateValuePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType, ODataMessageReaderSettings messageReaderSettings, out bool ignoreProperty)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");
            Debug.Assert(messageReaderSettings != null, "messageReaderSettings != null");

            ignoreProperty = false;

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

            IEdmProperty property = FindDefinedProperty(propertyName, owningStructuredType, messageReaderSettings);
            if (property == null && !owningStructuredType.IsOpen)
            {
                if (messageReaderSettings.UndeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty))
                {
                    ignoreProperty = true;
                }
                else
                {
                    throw new ODataException(Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
                }
            }

            return property;
        }
        /// <summary>
        /// Finds a defined property from the model if one is available.
        /// The structured type can be null if no metadata is available.
        /// </summary>
        /// <param name="propertyName">The name of the property to find.</param>
        /// <param name="owningStructuredType">The owning type of the property with name <paramref name="propertyName"/> 
        /// or null if no metadata is available.</param>
        /// <param name="messageReaderSettings">The message reader settings being used.</param>
        /// <returns>The <see cref="IEdmProperty"/> instance representing the property with name <paramref name="propertyName"/> 
        /// or null if no metadata is available.</returns>
        internal static IEdmProperty FindDefinedProperty(string propertyName, IEdmStructuredType owningStructuredType, ODataMessageReaderSettings messageReaderSettings)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");
            Debug.Assert(messageReaderSettings != null, "messageReaderSettings != null");

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

            IEdmProperty property = owningStructuredType.FindProperty(propertyName);

            if (property == null && owningStructuredType.IsOpen)
            {
                if (messageReaderSettings.UndeclaredPropertyBehaviorKinds != ODataUndeclaredPropertyBehaviorKinds.None)
                {
                    throw new ODataException(Strings.ReaderValidationUtils_UndeclaredPropertyBehaviorKindSpecifiedForOpenType(propertyName, owningStructuredType.ODataFullName()));
                }
            }

            return property;
        }
Beispiel #14
0
 internal static IEdmProperty ValidateValuePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType, ODataMessageReaderSettings messageReaderSettings, out bool ignoreProperty)
 {
     ignoreProperty = false;
     if (owningStructuredType == null)
     {
         return null;
     }
     IEdmProperty property = FindDefinedProperty(propertyName, owningStructuredType, messageReaderSettings);
     if ((property == null) && !owningStructuredType.IsOpen)
     {
         if (!messageReaderSettings.UndeclaredPropertyBehaviorKinds.HasFlag(ODataUndeclaredPropertyBehaviorKinds.IgnoreUndeclaredValueProperty))
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
         }
         ignoreProperty = true;
     }
     return property;
 }
        /// <summary>
        /// Build a segment from a token.
        /// </summary>
        /// <param name="tokenIn">the token to bind</param>
        /// <param name="model">The model.</param>
        /// <param name="edmType">the type of the current scope based on type segments.</param>
        /// <param name="resolver">Resolver for uri parser.</param>
        /// <returns>The segment created from the token.</returns>
        public static ODataPathSegment ConvertNonTypeTokenToSegment(PathSegmentToken tokenIn, IEdmModel model, IEdmStructuredType edmType, ODataUriResolver resolver = null)
        {
            if (resolver == null)
            {
                resolver = ODataUriResolver.Default;
            }

            ODataPathSegment nextSegment;

            if (TryBindAsDeclaredProperty(tokenIn, edmType, resolver, out nextSegment))
            {
                return(nextSegment);
            }

            // Operations must be container-qualified, and because the token type indicates it was not a .-seperated identifier, we should not try to look up operations.
            if (tokenIn.IsNamespaceOrContainerQualified())
            {
                if (TryBindAsOperation(tokenIn, model, edmType, out nextSegment))
                {
                    return(nextSegment);
                }

                // If an action or function is requested in a selectItem using a qualifiedActionName or a qualifiedFunctionName
                // and that operation cannot be bound to the entities requested, the service MUST ignore the selectItem.
                if (!edmType.IsOpen)
                {
                    return(null);
                }
            }

            if (edmType.IsOpen)
            {
                return(new OpenPropertySegment(tokenIn.Identifier));
            }

            throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(edmType.ODataFullName(), tokenIn.Identifier));
        }
        internal static IEdmProperty ValidatePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType)
        {
            if (owningStructuredType == null)
            {
                return(null);
            }
            IEdmProperty property = owningStructuredType.FindProperty(propertyName);

            if (!owningStructuredType.IsOpen && (property == null))
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
            }
            return(property);
        }
Beispiel #17
0
        /// <summary>
        /// Gets the property info for the EDM property declared on this type.
        /// </summary>
        /// <param name="structuredType">The structured type to get the property on.</param>
        /// <param name="property">Property instance to get the property info for.</param>
        /// <param name="model">The model containing annotations.</param>
        /// <returns>Returns the PropertyInfo object for the specified EDM property.</returns>
        internal PropertyInfo GetPropertyInfo(IEdmStructuredType structuredType, IEdmProperty property, IEdmModel model)
        {
            Debug.Assert(structuredType != null, "structuredType != null");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(model != null, "model != null");
            Debug.Assert(property.GetCanReflectOnInstanceTypeProperty(model), "property.CanReflectOnInstanceTypeProperty()");
#if DEBUG
            Debug.Assert(structuredType.ContainsProperty(property), "The structuredType does not define the specified property.");
#endif

            if (this.propertyInfosDeclaredOnThisType == null)
            {
                this.propertyInfosDeclaredOnThisType = new Dictionary <IEdmProperty, PropertyInfo>(ReferenceEqualityComparer <IEdmProperty> .Instance);
            }

            PropertyInfo propertyInfo;
            if (!this.propertyInfosDeclaredOnThisType.TryGetValue(property, out propertyInfo))
            {
                BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;
                propertyInfo = structuredType.GetInstanceType(model).GetProperty(property.Name, bindingFlags);
                if (propertyInfo == null)
                {
                    throw new ODataException(ODataErrorStrings.PropertyInfoTypeAnnotation_CannotFindProperty(structuredType.ODataFullName(), structuredType.GetInstanceType(model), property.Name));
                }

                this.propertyInfosDeclaredOnThisType.Add(property, propertyInfo);
            }

            Debug.Assert(propertyInfo != null, "propertyInfo != null");
            return(propertyInfo);
        }
        /// <summary>
        /// Validates that a property with the specified name exists on a given structured type.
        /// The structured type can be null if no metadata is available.
        /// </summary>
        /// <param name="propertyName">The name of the property to validate.</param>
        /// <param name="owningStructuredType">The owning type of the property with name <paramref name="propertyName"/>
        /// or null if no metadata is available.</param>
        /// <returns>The <see cref="IEdmProperty"/> instance representing the property with name <paramref name="propertyName"/>
        /// or null if no metadata is available.</returns>
        internal static IEdmProperty ValidatePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType)
        {
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");

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

            IEdmProperty property = owningStructuredType.FindProperty(propertyName);

            // verify that the property is declared if the type is not an open type.
            if (!owningStructuredType.IsOpen && property == null)
            {
                throw new ODataException(Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
            }

            return(property);
        }
        /// <summary>
        /// Generate an expand item (and a select item for the implicit nav prop if necessary) based on an ExpandTermToken
        /// </summary>
        /// <param name="tokenIn">the expandTerm token to visit</param>
        /// <returns>the expand item for this expand term token.</returns>
        private ExpandedNavigationSelectItem GenerateExpandItem(ExpandTermToken tokenIn)
        {
            ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn");

            // ensure that we're always dealing with proper V4 syntax
            if (tokenIn.PathToNavProp.NextToken != null && !tokenIn.PathToNavProp.IsNamespaceOrContainerQualified())
            {
                throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath);
            }

            PathSegmentToken currentToken = tokenIn.PathToNavProp;

            IEdmStructuredType      currentLevelEntityType = this.EdmType;
            List <ODataPathSegment> pathSoFar         = new List <ODataPathSegment>();
            PathSegmentToken        firstNonTypeToken = currentToken;

            if (currentToken.IsNamespaceOrContainerQualified())
            {
                pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(currentToken, this.Model, this.Settings.SelectExpandLimit, this.configuration.Resolver, ref currentLevelEntityType, out firstNonTypeToken));
            }

            IEdmProperty edmProperty = this.configuration.Resolver.ResolveProperty(currentLevelEntityType, firstNonTypeToken.Identifier);

            if (edmProperty == null)
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(currentLevelEntityType.ODataFullName(), currentToken.Identifier));
            }

            IEdmNavigationProperty currentNavProp = edmProperty as IEdmNavigationProperty;

            if (currentNavProp == null)
            {
                throw new ODataException(ODataErrorStrings.ExpandItemBinder_PropertyIsNotANavigationProperty(currentToken.Identifier, currentLevelEntityType.ODataFullName()));
            }

            if (firstNonTypeToken.NextToken != null)
            {
                // lastly... make sure that, since we're on a NavProp, that the next token isn't null.
                throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath);
            }

            pathSoFar.Add(new NavigationPropertySegment(currentNavProp, /*entitySet*/ null));
            ODataExpandPath pathToNavProp = new ODataExpandPath(pathSoFar);

            SelectExpandClause subSelectExpand;

            if (tokenIn.ExpandOption != null)
            {
                subSelectExpand = this.GenerateSubExpand(currentNavProp, tokenIn);
            }
            else
            {
                subSelectExpand = BuildDefaultSubExpand();
            }

            subSelectExpand = this.DecorateExpandWithSelect(subSelectExpand, currentNavProp, tokenIn.SelectOption);

            IEdmNavigationSource targetNavigationSource = null;

            if (this.NavigationSource != null)
            {
                targetNavigationSource = this.NavigationSource.FindNavigationTarget(currentNavProp);
            }

            // call MetadataBinder to build the filter clause
            FilterClause filterOption = null;

            if (tokenIn.FilterOption != null)
            {
                MetadataBinder binder       = this.BuildNewMetadataBinder(targetNavigationSource);
                FilterBinder   filterBinder = new FilterBinder(binder.Bind, binder.BindingState);
                filterOption = filterBinder.BindFilter(tokenIn.FilterOption);
            }

            // call MetadataBinder again to build the orderby clause
            OrderByClause orderbyOption = null;

            if (tokenIn.OrderByOptions != null)
            {
                MetadataBinder binder        = this.BuildNewMetadataBinder(targetNavigationSource);
                OrderByBinder  orderByBinder = new OrderByBinder(binder.Bind);
                orderbyOption = orderByBinder.BindOrderBy(binder.BindingState, tokenIn.OrderByOptions);
            }

            LevelsClause levelsOption = this.ParseLevels(tokenIn.LevelsOption, currentLevelEntityType, currentNavProp);

            SearchClause searchOption = null;

            if (tokenIn.SearchOption != null)
            {
                MetadataBinder binder       = this.BuildNewMetadataBinder(targetNavigationSource);
                SearchBinder   searchBinder = new SearchBinder(binder.Bind);
                searchOption = searchBinder.BindSearch(tokenIn.SearchOption);
            }

            return(new ExpandedNavigationSelectItem(pathToNavProp, targetNavigationSource, subSelectExpand, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption, levelsOption));
        }
        /// <summary>
        /// Validates that a property with the specified name exists on a given structured type.
        /// The structured type can be null if no metadata is available.
        /// </summary>
        /// <param name="propertyName">The name of the property to validate.</param>
        /// <param name="owningStructuredType">The owning type of the property with name <paramref name="propertyName"/> 
        /// or null if no metadata is available.</param>
        /// <param name="throwOnMissingProperty">Whether throw exception on missing property.</param>
        /// <returns>The <see cref="IEdmProperty"/> instance representing the property with name <paramref name="propertyName"/> 
        /// or null if no metadata is available.</returns>
        internal static IEdmProperty ValidatePropertyDefined(
            string propertyName,
            IEdmStructuredType owningStructuredType,
            bool throwOnMissingProperty = true)
        {
            Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)");

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

            IEdmProperty property = owningStructuredType.FindProperty(propertyName);

            // verify that the property is declared if the type is not an open type.
            if (throwOnMissingProperty && !owningStructuredType.IsOpen && property == null)
            {
                throw new ODataException(Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.ODataFullName()));
            }

            return property;
        }
        /// <summary>
        /// Resolve property from property name
        /// </summary>
        /// <param name="type">The declaring type.</param>
        /// <param name="propertyName">The property name.</param>
        /// <returns>The resolved <see cref="IEdmProperty"/></returns>
        public virtual IEdmProperty ResolveProperty(IEdmStructuredType type, string propertyName)
        {
            if (EnableCaseInsensitive)
            {
                var result = type.Properties()
                .Where(_ => string.Equals(propertyName, _.Name, StringComparison.OrdinalIgnoreCase))
                .ToList();

                if (result.Count == 1)
                {
                    return result.Single();
                }
                else if (result.Count > 1)
                {
                    throw new ODataException(Strings.UriParserMetadata_MultipleMatchingPropertiesFound(propertyName, type.ODataFullName()));
                }
            }

            return type.FindProperty(propertyName);
        }