private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationDisabled(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            switch (expectedTypeKind)
            {
            case EdmTypeKind.Entity:
            {
                if (((payloadType == null) || (expectedTypeKind != payloadType.TypeKind)) || !expectedTypeReference.AsEntity().EntityDefinition().IsAssignableFrom(((IEdmEntityType)payloadType)))
                {
                    break;
                }
                IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
                serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
                return(targetTypeReference);
            }

            case EdmTypeKind.Complex:
                if ((payloadType != null) && (expectedTypeKind == payloadType.TypeKind))
                {
                    VerifyComplexType(expectedTypeReference, payloadType, false);
                }
                break;

            case EdmTypeKind.Collection:
                if ((payloadType != null) && (expectedTypeKind == payloadType.TypeKind))
                {
                    VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                }
                break;

            default:
                throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);
            return(expectedTypeReference);
        }
Esempio n. 2
0
        /// <summary>
        /// Constructor which used when the nested resource info is a undeclared property in model.
        /// </summary>
        /// <param name="nestedResourceInfo">The nested resource info to report.</param>
        /// <param name="nestedProperty">The nested property for which the nested resource info will be reported.</param>
        /// <param name="nestedResourceType">The resource type of the nested resource info.</param>
        /// <param name="isExpanded">true if the nested resource info is expanded.</param>
        private ODataJsonLightReaderNestedResourceInfo(ODataNestedResourceInfo nestedResourceInfo, IEdmProperty nestedProperty, IEdmType nestedResourceType, bool isExpanded)
            : base(nestedProperty)
        {
            Debug.Assert(nestedResourceInfo != null, "nestedResourceInfo != null");
            Debug.Assert(nestedResourceType != null || nestedProperty != null, "nestedResourceType and nestedProperty are both null");

            this.nestedResourceInfo = nestedResourceInfo;

            // We get the nullablity from the nestedProperty if it exists otherwise we consider the resource to be nullable if only the nestedResourceType is specified.
            bool resourceTypeNullable = true;

            if (nestedProperty != null && nestedProperty.Type != null)
            {
                resourceTypeNullable = nestedProperty.Type.IsNullable;
            }

            IEdmType nestedType = nestedResourceType;

            // We get the resource type from the nestedProperty if not specified.
            if (nestedProperty != null && nestedType == null)
            {
                nestedType = nestedProperty.Type.Definition;
            }

            NestedResourceTypeReference = nestedType.ToTypeReference(resourceTypeNullable);
            this.hasValue = isExpanded;
        }
Esempio n. 3
0
        /// <summary>
        /// Parses an <paramref name="orderBy "/> clause on the given <paramref name="elementType"/>, binding
        /// the text into semantic nodes using the provided model.
        /// </summary>
        /// <param name="orderBy">String representation of the orderby expression.</param>
        /// <param name="configuration">The configuration used for binding.</param>
        /// <param name="elementType">Type that the orderby clause refers to.</param>
        /// <param name="navigationSource">NavigationSource that the elements are from.</param>
        /// <returns>An <see cref="OrderByClause"/> representing the metadata bound orderby expression.</returns>
        private OrderByClause ParseOrderByImplementation(string orderBy, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource)
        {
            ExceptionUtils.CheckArgumentNotNull(configuration, "configuration");
            ExceptionUtils.CheckArgumentNotNull(configuration.Model, "model");
            ExceptionUtils.CheckArgumentNotNull(elementType, "elementType");
            ExceptionUtils.CheckArgumentNotNull(orderBy, "orderBy");

            // Get the syntactic representation of the orderby expression
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.OrderByLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier);
            var orderByQueryTokens = expressionParser.ParseOrderBy(orderBy);

            // Bind it to metadata
            BindingState state = new BindingState(configuration);

            state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource);
            state.RangeVariables.Push(state.ImplicitRangeVariable);
            if (applyClause != null)
            {
                state.AggregatedPropertyNames = applyClause.GetLastAggregatedPropertyNames();
            }

            MetadataBinder binder        = new MetadataBinder(state);
            OrderByBinder  orderByBinder = new OrderByBinder(binder.Bind);
            OrderByClause  orderByClause = orderByBinder.BindOrderBy(state, orderByQueryTokens);

            return(orderByClause);
        }
Esempio n. 4
0
        /// <summary>
        /// Parses a <paramref name="filter"/> clause on the given <paramref name="elementType"/>, binding
        /// the text into semantic nodes using the provided model.
        /// </summary>
        /// <param name="filter">String representation of the filter expression.</param>
        /// <param name="configuration">The configuration used for binding.</param>
        /// <param name="elementType">Type that the filter clause refers to.</param>
        /// <param name="navigationSource">Navigation source that the elements being filtered are from.</param>
        /// <returns>A <see cref="FilterClause"/> representing the metadata bound filter expression.</returns>
        private FilterClause ParseFilterImplementation(string filter, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource)
        {
            ExceptionUtils.CheckArgumentNotNull(configuration, "configuration");
            ExceptionUtils.CheckArgumentNotNull(elementType, "elementType");
            ExceptionUtils.CheckArgumentNotNull(filter, "filter");

            // Get the syntactic representation of the filter expression
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.FilterLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier);
            QueryToken filterToken = expressionParser.ParseFilter(filter);

            // Bind it to metadata
            BindingState state = new BindingState(configuration);

            state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource);
            state.RangeVariables.Push(state.ImplicitRangeVariable);
            if (applyClause != null)
            {
                state.AggregatedPropertyNames = applyClause.GetLastAggregatedPropertyNames();
            }

            MetadataBinder binder       = new MetadataBinder(state);
            FilterBinder   filterBinder = new FilterBinder(binder.Bind, state);
            FilterClause   boundNode    = filterBinder.BindFilter(filterToken);

            return(boundNode);
        }
        internal static IEdmTypeReference ResolveAndValidateNonPrimitiveTargetType(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, EdmTypeKind payloadTypeKind, IEdmType payloadType, string payloadTypeName, IEdmModel model, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            bool flag = (messageReaderSettings.ReaderBehavior.TypeResolver != null) && (payloadType != null);

            if (!flag)
            {
                ValidateTypeSupported(expectedTypeReference, version);
                if (model.IsUserModel() && ((expectedTypeReference == null) || !messageReaderSettings.DisableStrictMetadataValidation))
                {
                    VerifyPayloadTypeDefined(payloadTypeName, payloadType);
                }
            }
            else
            {
                ValidateTypeSupported((payloadType == null) ? null : payloadType.ToTypeReference(true), version);
            }
            if ((payloadTypeKind != EdmTypeKind.None) && (!messageReaderSettings.DisableStrictMetadataValidation || (expectedTypeReference == null)))
            {
                ValidationUtils.ValidateTypeKind(payloadTypeKind, expectedTypeKind, payloadTypeName);
            }
            serializationTypeNameAnnotation = null;
            if (!model.IsUserModel())
            {
                return(null);
            }
            if ((expectedTypeReference == null) || flag)
            {
                return(ResolveAndValidateTargetTypeWithNoExpectedType(expectedTypeKind, payloadType, payloadTypeName, out serializationTypeNameAnnotation));
            }
            if (messageReaderSettings.DisableStrictMetadataValidation)
            {
                return(ResolveAndValidateTargetTypeStrictValidationDisabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation));
            }
            return(ResolveAndValidateTargetTypeStrictValidationEnabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation));
        }
        /// <summary>
        /// Resolves the given type if a client type resolver is available.
        /// </summary>
        /// <param name="typeToResolve">Type to resolve.</param>
        /// <returns>The resolved type.</returns>
        private IEdmType ResolveType(IEdmType typeToResolve)
        {
            Debug.Assert(typeToResolve != null, "typeToResolve != null");
            Debug.Assert(this.model != null, "model != null");
            Debug.Assert(this.readerBehavior != null, "readerBehavior != null");

            Func <IEdmType, string, IEdmType> customTypeResolver = this.readerBehavior.TypeResolver;

            if (customTypeResolver == null)
            {
                return(typeToResolve);
            }

            Debug.Assert(this.readerBehavior.ApiBehaviorKind == ODataBehaviorKind.WcfDataServicesClient, "Custom type resolver can only be specified in WCF DS Client behavior.");
            EdmTypeKind typeKind;

            // MetadataUtils.ResolveTypeName() does not allow entity collection types however both operationImport.ReturnType and operationParameter.Type can be of entity collection types.
            // We don't want to relax MetadataUtils.ResolveTypeName() since the rest of ODL only allows primitive and complex collection types and is currently relying on the method to
            // enforce this.  So if typeToResolve is an entity collection type, we will resolve the item type and reconstruct the collection type from the resolved item type.
            IEdmCollectionType collectionTypeToResolve = typeToResolve as IEdmCollectionType;

            if (collectionTypeToResolve != null && collectionTypeToResolve.ElementType.IsEntity())
            {
                IEdmTypeReference itemTypeReferenceToResolve = collectionTypeToResolve.ElementType;
                IEdmType          resolvedItemType           = MetadataUtils.ResolveTypeName(this.model, null /*expectedType*/, itemTypeReferenceToResolve.FullName(), customTypeResolver, this.version, out typeKind);
                return(new EdmCollectionType(resolvedItemType.ToTypeReference(itemTypeReferenceToResolve.IsNullable)));
            }

            return(MetadataUtils.ResolveTypeName(this.model, null /*expectedType*/, typeToResolve.ODataFullName(), customTypeResolver, this.version, out typeKind));
        }
Esempio n. 7
0
        /// <summary>
        /// Resolves the given type if a client type resolver is available.
        /// </summary>
        /// <param name="typeToResolve">Type to resolve.</param>
        /// <returns>The resolved type.</returns>
        private IEdmType ResolveType(IEdmType typeToResolve)
        {
            Debug.Assert(typeToResolve != null, "typeToResolve != null");
            Debug.Assert(this.model != null, "model != null");

            if (clientCustomTypeResolver == null)
            {
                return(typeToResolve);
            }

            EdmTypeKind typeKind;

            // MetadataUtils.ResolveTypeName() does not allow entity collection types however both operationImport.ReturnType and operationParameter.Type can be of entity collection types.
            // We don't want to relax MetadataUtils.ResolveTypeName() since the rest of ODL only allows primitive and complex collection types and is currently relying on the method to
            // enforce this.  So if typeToResolve is an entity collection type, we will resolve the item type and reconstruct the collection type from the resolved item type.
            IEdmCollectionType collectionTypeToResolve = typeToResolve as IEdmCollectionType;

            if (collectionTypeToResolve != null && collectionTypeToResolve.ElementType.IsEntity())
            {
                IEdmTypeReference itemTypeReferenceToResolve = collectionTypeToResolve.ElementType;
                IEdmType          resolvedItemType           = MetadataUtils.ResolveTypeName(this.model, null /*expectedType*/, itemTypeReferenceToResolve.FullName(), clientCustomTypeResolver, out typeKind);
                return(new EdmCollectionType(resolvedItemType.ToTypeReference(itemTypeReferenceToResolve.IsNullable)));
            }

            return(MetadataUtils.ResolveTypeName(this.model, null /*expectedType*/, typeToResolve.FullTypeName(), clientCustomTypeResolver, out typeKind));
        }
Esempio n. 8
0
        /// <summary>
        /// Resolve a type name against the provided <paramref name="model"/>. If no type name is given we either throw (if a type name on the value is required, e.g., on entries)
        /// or infer the type from the model (if it is a user model).
        /// </summary>
        /// <param name="model">The model to use.</param>
        /// <param name="typeReferenceFromMetadata">The type inferred from the model or null if the model is not a user model.</param>
        /// <param name="typeName">The type name to be resolved.</param>
        /// <param name="typeKindFromValue">The expected type kind of the resolved type.</param>
        /// <param name="isOpenPropertyType">True if the type name belongs to an open property.</param>
        /// <returns>A type for the <paramref name="typeName"/> or null if no metadata is available.</returns>
        internal static IEdmTypeReference ResolveTypeNameForWriting(IEdmModel model, IEdmTypeReference typeReferenceFromMetadata, ref string typeName, EdmTypeKind typeKindFromValue, bool isOpenPropertyType)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(model != null, "model != null");
            Debug.Assert(
                typeKindFromValue == EdmTypeKind.Complex || typeKindFromValue == EdmTypeKind.Collection,
                "Only complex or collection types are supported by this method. This method assumes that the types in question don't support inheritance.");

            IEdmType          typeFromValue          = WriterValidationUtils.ValidateValueTypeName(model, typeName, typeKindFromValue, isOpenPropertyType);
            IEdmTypeReference typeReferenceFromValue = typeFromValue.ToTypeReference();

            if (typeReferenceFromMetadata != null)
            {
                ValidationUtils.ValidateTypeKind(
                    typeKindFromValue,
                    typeReferenceFromMetadata.TypeKind(),
                    typeFromValue == null ? null : typeFromValue.ODataFullName());
            }

            typeReferenceFromValue = ValidateMetadataType(typeReferenceFromMetadata, typeReferenceFromValue);

            if (typeKindFromValue == EdmTypeKind.Collection && typeReferenceFromValue != null)
            {
                // validate that the collection type represents a valid Collection type (e.g., is unordered).
                typeReferenceFromValue = ValidationUtils.ValidateCollectionType(typeReferenceFromValue);
            }

            // derive the type name from the metadata if available
            if (typeName == null && typeReferenceFromValue != null)
            {
                typeName = typeReferenceFromValue.ODataFullName();
            }

            return(typeReferenceFromValue);
        }
Esempio n. 9
0
        /// <summary>
        /// Verifies that the given <paramref name="primitiveValue"/> is or can be coerced to <paramref name="expectedTypeReference"/>, and coerces it if necessary.
        /// </summary>
        /// <param name="primitiveValue">An EDM primitive value to verify.</param>
        /// <param name="model">Model to verify against.</param>
        /// <param name="expectedTypeReference">Expected type reference.</param>
        /// <param name="version">The version to use for reading.</param>
        /// <returns>Coerced version of the <paramref name="primitiveValue"/>.</returns>
        internal static object VerifyAndCoerceUriPrimitiveLiteral(object primitiveValue, IEdmModel model, IEdmTypeReference expectedTypeReference, ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(primitiveValue, "primitiveValue");
            ExceptionUtils.CheckArgumentNotNull(model, "model");
            ExceptionUtils.CheckArgumentNotNull(expectedTypeReference, "expectedTypeReference");

            // First deal with null literal
            ODataUriNullValue nullValue = primitiveValue as ODataUriNullValue;

            if (nullValue != null)
            {
                if (!expectedTypeReference.IsNullable)
                {
                    throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralNullOnNonNullableType(expectedTypeReference.ODataFullName()));
                }

                IEdmType actualResolvedType = ValidationUtils.ValidateValueTypeName(model, nullValue.TypeName, expectedTypeReference.Definition.TypeKind);
                Debug.Assert(actualResolvedType != null, "This is a primitive-only codepath so actualResolvedType != null.");

                if (actualResolvedType.IsSpatial())
                {
                    ODataVersionChecker.CheckSpatialValue(version);
                }

                if (TypePromotionUtils.CanConvertTo(actualResolvedType.ToTypeReference(), expectedTypeReference))
                {
                    nullValue.TypeName = expectedTypeReference.ODataFullName();
                    return(nullValue);
                }

                throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralNullTypeVerificationFailure(expectedTypeReference.ODataFullName(), nullValue.TypeName));
            }

            // Only other positive case is a numeric primitive that needs to be coerced
            IEdmPrimitiveTypeReference expectedPrimitiveTypeReference = expectedTypeReference.AsPrimitiveOrNull();

            if (expectedPrimitiveTypeReference == null)
            {
                throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedTypeReference.ODataFullName(), primitiveValue));
            }

            object coercedResult = CoerceNumericType(primitiveValue, expectedPrimitiveTypeReference.PrimitiveDefinition());

            if (coercedResult != null)
            {
                return(coercedResult);
            }

            Type actualType = primitiveValue.GetType();
            Type targetType = TypeUtils.GetNonNullableType(EdmLibraryExtensions.GetPrimitiveClrType(expectedPrimitiveTypeReference));

            // If target type is assignable from actual type, we're OK
            if (targetType.IsAssignableFrom(actualType))
            {
                return(primitiveValue);
            }

            throw new ODataException(o.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedPrimitiveTypeReference.ODataFullName(), primitiveValue));
        }
Esempio n. 10
0
 private static IEdmTypeReference GetNullablePayloadTypeReference(IEdmType payloadType)
 {
     if (payloadType != null)
     {
         return(payloadType.ToTypeReference(true));
     }
     return(null);
 }
Esempio n. 11
0
 internal static IEdmCollectionType GetCollectionType(IEdmType itemType)
 {
     if (!itemType.IsODataPrimitiveTypeKind() && !itemType.IsODataComplexTypeKind())
     {
         throw new ODataException(Microsoft.Data.OData.Strings.EdmLibraryExtensions_CollectionItemCanBeOnlyPrimitiveOrComplex);
     }
     return(new EdmCollectionType(itemType.ToTypeReference()));
 }
Esempio n. 12
0
 private static IEdmTypeReference GetNullablePayloadTypeReference(IEdmType payloadType)
 {
     if (payloadType != null)
     {
         return payloadType.ToTypeReference(true);
     }
     return null;
 }
Esempio n. 13
0
        /// <summary>Helper method to get a type by its name.</summary>
        /// <param name="model">The model.</param>
        /// <param name="fullName">The name of the type to find. For the namespace the namespace of the model is used.</param>
        /// <param name="nullable">true if the type reference should be nullable; otherwise false.</param>
        /// <returns>The type found.</returns>
        public static IEdmTypeReference ResolveTypeReference(this IEdmModel model, string fullName, bool nullable)
        {
            IEdmType type = ResolveType(model, fullName);

            ExceptionUtilities.Assert(type != null, "type != null");

            return(type.ToTypeReference(nullable));
        }
        /// <summary>
        /// Gets or adds the expected type annotation.
        /// </summary>
        /// <param name="payloadElement">The payload element to get or add the annotation to.</param>
        /// <returns>The expected type annotation to use.</returns>
        public static ExpectedTypeODataPayloadElementAnnotation AddExpectedTypeAnnotation(this ODataPayloadElement payloadElement, IEdmType expectedType)
        {
            Debug.Assert(payloadElement != null, "payloadElement != null");

            var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>();

            if (expectedTypeAnnotation == null)
            {
                expectedTypeAnnotation = new ExpectedTypeODataPayloadElementAnnotation();
                payloadElement.SetAnnotation(expectedTypeAnnotation);
            }

            expectedTypeAnnotation.EdmExpectedType = expectedType.ToTypeReference();
            return(expectedTypeAnnotation);
        }
Esempio n. 15
0
        private static IEdmTypeReference ResolveAndValidateTargetTypeWithNoExpectedType(EdmTypeKind expectedTypeKind, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            serializationTypeNameAnnotation = null;
            if (payloadType == null)
            {
                if (expectedTypeKind == EdmTypeKind.Entity)
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_EntryWithoutType);
                }
                throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_ValueWithoutType);
            }
            IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);

            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
            return(targetTypeReference);
        }
Esempio n. 16
0
        internal static IEdmTypeReference ResolveTypeNameForWriting(IEdmModel model, IEdmTypeReference typeReferenceFromMetadata, ref string typeName, EdmTypeKind typeKindFromValue, bool isOpenPropertyType)
        {
            IEdmType          type = ValidateValueTypeName(model, typeName, typeKindFromValue, isOpenPropertyType);
            IEdmTypeReference typeReferenceFromValue = type.ToTypeReference();

            if (typeReferenceFromMetadata != null)
            {
                ValidationUtils.ValidateTypeKind(typeKindFromValue, typeReferenceFromMetadata.TypeKind(), (type == null) ? null : type.ODataFullName());
            }
            typeReferenceFromValue = ValidateMetadataType(typeReferenceFromMetadata, typeReferenceFromValue);
            if ((typeKindFromValue == EdmTypeKind.Collection) && (typeReferenceFromValue != null))
            {
                typeReferenceFromValue = ValidationUtils.ValidateCollectionType(typeReferenceFromValue);
            }
            if ((typeName == null) && (typeReferenceFromValue != null))
            {
                typeName = typeReferenceFromValue.ODataFullName();
            }
            return(typeReferenceFromValue);
        }
 internal static object VerifyAndCoerceUriPrimitiveLiteral(object primitiveValue, IEdmModel model, IEdmTypeReference expectedTypeReference, ODataVersion version)
 {
     ExceptionUtils.CheckArgumentNotNull<object>(primitiveValue, "primitiveValue");
     ExceptionUtils.CheckArgumentNotNull<IEdmModel>(model, "model");
     ExceptionUtils.CheckArgumentNotNull<IEdmTypeReference>(expectedTypeReference, "expectedTypeReference");
     ODataUriNullValue value2 = primitiveValue as ODataUriNullValue;
     if (value2 != null)
     {
         if (!expectedTypeReference.IsNullable)
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralNullOnNonNullableType(expectedTypeReference.ODataFullName()));
         }
         IEdmType type = ValidationUtils.ValidateValueTypeName(model, value2.TypeName, expectedTypeReference.Definition.TypeKind);
         if (type.IsSpatial())
         {
             ODataVersionChecker.CheckSpatialValue(version);
         }
         if (!TypePromotionUtils.CanConvertTo(type.ToTypeReference(), expectedTypeReference))
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralNullTypeVerificationFailure(expectedTypeReference.ODataFullName(), value2.TypeName));
         }
         value2.TypeName = expectedTypeReference.ODataFullName();
         return value2;
     }
     IEdmPrimitiveTypeReference reference = expectedTypeReference.AsPrimitiveOrNull();
     if (reference == null)
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedTypeReference.ODataFullName(), primitiveValue));
     }
     object obj2 = CoerceNumericType(primitiveValue, reference.PrimitiveDefinition());
     if (obj2 != null)
     {
         return obj2;
     }
     Type c = primitiveValue.GetType();
     if (!TypeUtils.GetNonNullableType(EdmLibraryExtensions.GetPrimitiveClrType(reference)).IsAssignableFrom(c))
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(reference.ODataFullName(), primitiveValue));
     }
     return primitiveValue;
 }
Esempio n. 18
0
        /// <summary>
        /// Parses an <paramref name="apply"/> clause on the given <paramref name="elementType"/>, binding
        /// the text into a metadata-bound or dynamic properties to be applied using the provided model.
        /// </summary>
        /// <param name="apply">String representation of the apply expression.</param>
        /// <param name="configuration">The configuration used for binding.</param>
        /// <param name="elementType">Type that the apply clause refers to.</param>
        /// <param name="navigationSource">Navigation source that the elements being filtered are from.</param>
        /// <returns>A <see cref="ApplyClause"/> representing the metadata bound apply expression.</returns>
        private static ApplyClause ParseApplyImplementation(string apply, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource)
        {
            ExceptionUtils.CheckArgumentNotNull(configuration, "configuration");
            ExceptionUtils.CheckArgumentNotNull(elementType, "elementType");
            ExceptionUtils.CheckArgumentNotNull(apply, "apply");

            // Get the syntactic representation of the apply expression
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.FilterLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier);
            var applyTokens = expressionParser.ParseApply(apply);

            // Bind it to metadata
            BindingState state = new BindingState(configuration);

            state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource);
            state.RangeVariables.Push(state.ImplicitRangeVariable);
            MetadataBinder binder      = new MetadataBinder(state);
            ApplyBinder    applyBinder = new ApplyBinder(binder.Bind, state);
            ApplyClause    boundNode   = applyBinder.BindApply(applyTokens);

            return(boundNode);
        }
Esempio n. 19
0
        /// <summary>
        /// Resolve a resource type name
        /// </summary>
        /// <param name="model">The model to use.</param>
        /// <param name="expectedType">The type inferred from the model or null if the model is not a user model.</param>
        /// <param name="typeName">Name of the type to resolve.</param>
        /// <param name="writerValidator">The writer validator to use for validation.</param>
        /// <returns>A type for primitive value</returns>
        internal static IEdmStructuredType ResolveAndValidateTypeFromTypeName(IEdmModel model, IEdmStructuredType expectedType, string typeName, IWriterValidator writerValidator)
        {
            if (typeName == null && expectedType != null)
            {
                return(expectedType);
            }

            // TODO: Clean up handling of expected types/sets during writing
            IEdmType          typeFromResource       = ResolveAndValidateTypeName(model, typeName, EdmTypeKind.None, /* expectStructuredType */ true, writerValidator);
            IEdmTypeReference typeReferenceFromValue = ResolveTypeFromMetadataAndValue(
                expectedType.ToTypeReference(),
                typeFromResource == null ? null : typeFromResource.ToTypeReference(),
                writerValidator);

            if (typeReferenceFromValue != null && typeReferenceFromValue.IsUntyped())
            {
                return(new EdmUntypedStructuredType());
            }

            return(typeReferenceFromValue == null ? null : typeReferenceFromValue.ToStructuredType());
        }
Esempio n. 20
0
        /// <summary>
        /// Parses a <paramref name="query"/> clause on the given <paramref name="elementType"/>, binding
        /// the text into semantic nodes using the provided model.
        /// </summary>
        /// <param name="query">String representation of the filter expression.</param>
        /// <param name="configuration">The configuration used for binding.</param>
        /// <param name="elementType">Type that the filter clause refers to.</param>
        /// <param name="navigationSource">Navigation source that the elements being filtered are from.</param>
        /// <returns>A <see cref="FilterClause"/> representing the metadata bound filter expression.</returns>
        internal static ExpressionClause ParseExpressionImplementation(string query, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource)
        {
            ExceptionUtils.CheckArgumentNotNull(configuration, "configuration");
            ExceptionUtils.CheckArgumentNotNull(elementType, "elementType");
            ExceptionUtils.CheckArgumentNotNull(query, "query");

            // Get the syntactic representation of the filter expression
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.FilterLimit);
            QueryToken expressionToken = expressionParser.ParseFilter(query);

            // Bind it to metadata
            BindingState state = new BindingState(configuration);

            state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource);
            state.RangeVariables.Push(state.ImplicitRangeVariable);
            MetadataBinder   binder       = new MetadataBinder(state);
            FilterBinder     filterBinder = new FilterBinder(binder.Bind, state);
            ExpressionClause boundNode    = filterBinder.BindProperyExpression(expressionToken);

            return(boundNode);
        }
Esempio n. 21
0
        /// <summary>
        /// Parses a <paramref name="orderBy "/> clause on the given <paramref name="elementType"/>, binding
        /// the text into semantic nodes using the provided model.
        /// </summary>
        /// <param name="orderBy">String representation of the orderby expression.</param>
        /// <param name="elementType">Type that the orderby clause refers to.</param>
        /// <param name="entitySet">EntitySet that the elements beign filtered are from.</param>
        /// <returns>A <see cref="OrderByClause"/> representing the metadata bound orderby expression.</returns>
        private OrderByClause ParseOrderByImplementation(string orderBy, IEdmType elementType, IEdmEntitySet entitySet)
        {
            ExceptionUtils.CheckArgumentNotNull(this.configuration.Model, "model");
            ExceptionUtils.CheckArgumentNotNull(elementType, "elementType");
            ExceptionUtils.CheckArgumentNotNull(orderBy, "orderBy");

            // Get the syntactic representation of the filter expression
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(this.Settings.OrderByLimit);
            var orderByQueryTokens = expressionParser.ParseOrderBy(orderBy);

            // Bind it to metadata
            BindingState state = new BindingState(this.configuration);

            state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), entitySet);
            state.RangeVariables.Push(state.ImplicitRangeVariable);
            MetadataBinder binder        = new MetadataBinder(state);
            OrderByBinder  orderByBinder = new OrderByBinder(binder.Bind);
            OrderByClause  orderByClause = orderByBinder.BindOrderBy(state, orderByQueryTokens);

            return(orderByClause);
        }
Esempio n. 22
0
        /// <summary>
        /// Parses a <paramref name="filter"/> clause on the given <paramref name="elementType"/>, binding
        /// the text into semantic nodes using the provided.
        /// </summary>
        /// <param name="filter">String representation of the filter expression.</param>
        /// <param name="elementType">Type that the filter clause refers to.</param>
        /// <param name="entitySet">EntitySet that the elements beign filtered are from.</param>
        /// <returns>A <see cref="FilterClause"/> representing the metadata bound filter expression.</returns>
        private FilterClause ParseFilterImplementation(string filter, IEdmType elementType, IEdmEntitySet entitySet)
        {
            ExceptionUtils.CheckArgumentNotNull(this.configuration, "this.configuration");
            ExceptionUtils.CheckArgumentNotNull(elementType, "elementType");
            ExceptionUtils.CheckArgumentNotNull(filter, "filter");

            // Get the syntactic representation of the filter expression
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(this.Settings.FilterLimit);
            QueryToken filterToken = expressionParser.ParseFilter(filter);

            // Bind it to metadata
            BindingState state = new BindingState(this.configuration);

            state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), entitySet);
            state.RangeVariables.Push(state.ImplicitRangeVariable);
            MetadataBinder binder       = new MetadataBinder(state);
            FilterBinder   filterBinder = new FilterBinder(binder.Bind, state);
            FilterClause   boundNode    = filterBinder.BindFilter(filterToken);

            return(boundNode);
        }
Esempio n. 23
0
        /// <summary>
        /// Resolve a type name against the provided <paramref name="model"/>. If not payload type name is specified,
        /// derive the type from the model type (if available).
        /// </summary>
        /// <param name="model">The model to use.</param>
        /// <param name="typeReferenceFromMetadata">The type inferred from the model or null if the model is not a user model.</param>
        /// <param name="resourceValue">The value in question to resolve the type for.</param>
        /// <param name="isOpenPropertyType">True if the type name belongs to an open (dynamic) property.</param>
        /// <param name="writerValidator">The writer validator to use for validation.</param>
        /// <returns>A type for the <paramref name="resourceValue"/> or null if no type name is specified and no metadata is available.</returns>
        internal static IEdmTypeReference ResolveAndValidateTypeForResourceValue(IEdmModel model, IEdmTypeReference typeReferenceFromMetadata,
                                                                                 ODataResourceValue resourceValue, bool isOpenPropertyType, IWriterValidator writerValidator)
        {
            Debug.Assert(model != null, "model != null");
            Debug.Assert(resourceValue != null, "resourceValue != null");

            var typeName = resourceValue.TypeName;

            ValidateIfTypeNameMissing(typeName, model, isOpenPropertyType);

            // It's ok to use "EdmTypeKind.Complex" because the validation will check "IsStructured()".
            IEdmType typeFromValue = typeName == null ? null : ResolveAndValidateTypeName(model, typeName, EdmTypeKind.Complex, true, writerValidator);

            if (typeReferenceFromMetadata != null)
            {
                // It's ok to use "EdmTypeKind.Complex" because the parameter "expectStructuredType" is set to "true".
                writerValidator.ValidateTypeKind(EdmTypeKind.Complex, typeReferenceFromMetadata.TypeKind(), true, typeFromValue);
            }

            return(ResolveTypeFromMetadataAndValue(typeReferenceFromMetadata,
                                                   typeFromValue == null ? null : typeFromValue.ToTypeReference(), writerValidator));
        }
Esempio n. 24
0
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationEnabled(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            switch (expectedTypeKind)
            {
            case EdmTypeKind.Entity:
            {
                if (payloadType == null)
                {
                    break;
                }
                IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
                ValidationUtils.ValidateEntityTypeIsAssignable((IEdmEntityTypeReference)expectedTypeReference, (IEdmEntityTypeReference)targetTypeReference);
                serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
                return(targetTypeReference);
            }

            case EdmTypeKind.Complex:
                if (payloadType != null)
                {
                    VerifyComplexType(expectedTypeReference, payloadType, true);
                }
                break;

            case EdmTypeKind.Collection:
                if ((payloadType != null) && (string.CompareOrdinal(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()) != 0))
                {
                    VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                    throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_IncompatibleType(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()));
                }
                break;

            default:
                throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);
            return(expectedTypeReference);
        }
        /// <summary>
        /// Returns the IEdmCollectionType implementation with the given IEdmTypeReference as element type.
        /// </summary>
        /// <param name="itemType">IEdmTypeReference instance which is the element type.</param>
        /// <returns>An <see cref="IEdmCollectionType"/> instance using the <paramref name="itemType"/> as Collection item type.</returns>
        internal static IEdmCollectionType GetCollectionType(IEdmType itemType)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(itemType != null, "itemType != null");

            IEdmTypeReference itemTypeReference;
            if (itemType.IsODataPrimitiveTypeKind() || itemType.IsODataComplexTypeKind())
            {
                itemTypeReference = itemType.ToTypeReference();
            }
            else
            {
                throw new ODataException(Strings.EdmLibraryExtensions_CollectionItemCanBeOnlyPrimitiveOrComplex);
            }

            return new EdmCollectionType(itemTypeReference);
        }
 /// <summary>
 /// Sets the expected base entity type for the top-level entity set.
 /// </summary>
 /// <param name="entitySetInstance">The entity set instance to set the expected set for.</param>
 /// <param name="entitySet">The entity set the entities belong to.</param>
 /// <param name="baseEntityType">The base entity type to set as the expected base entity type.</param>
 /// <returns>The <paramref name="entitySetInstance"/> after its expected type was set.</returns>
 public static EntitySetInstance ExpectedEntityType(this EntitySetInstance entitySetInstance, IEdmType baseEntityType, IEdmEntitySet entitySet = null, bool nullable = false)
 {
     return(entitySetInstance.ExpectedEntityType(baseEntityType.ToTypeReference(nullable), entitySet));
 }
        /// <summary>
        /// Verifies that in case of collection types, the item type is valid.
        /// </summary>
        /// <param name="expectedTypeReference">The expected type reference.</param>
        /// <param name="payloadType">The payload type.</param>
        /// <remarks>
        /// This method verifies that item type is compatible with expected type.
        /// </remarks>
        private static void VerifyCollectionComplexItemType(IEdmTypeReference expectedTypeReference, IEdmType payloadType)
        {
            Debug.Assert(expectedTypeReference != null, "expectedTypeReference != null");
            Debug.Assert(payloadType != null, "payloadType != null");
            Debug.Assert(expectedTypeReference.IsNonEntityCollectionType(), "This method only works on atomic collections.");
            Debug.Assert(payloadType.IsNonEntityCollectionType(), "This method only works on atomic collections.");

            IEdmCollectionTypeReference collectionTypeReference = ValidationUtils.ValidateCollectionType(expectedTypeReference);
            IEdmTypeReference expectedItemTypeReference = collectionTypeReference.GetCollectionItemType();
            if (expectedItemTypeReference != null && expectedItemTypeReference.IsODataComplexTypeKind())
            {
                IEdmCollectionTypeReference payloadCollectionTypeReference = ValidationUtils.ValidateCollectionType(payloadType.ToTypeReference());
                IEdmTypeReference payloadItemTypeReference = payloadCollectionTypeReference.GetCollectionItemType();
                if (payloadItemTypeReference != null && payloadItemTypeReference.IsODataComplexTypeKind())
                {
                    // Note that this method is called from both strict and lax code paths, so we must not fail if the types are not related.
                    VerifyComplexType(expectedItemTypeReference, payloadItemTypeReference.Definition, /* failIfNotRelated */ false);
                }
            }
        }
Esempio n. 28
0
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationEnabled(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            switch (expectedTypeKind)
            {
                case EdmTypeKind.Entity:
                {
                    if (payloadType == null)
                    {
                        break;
                    }
                    IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
                    ValidationUtils.ValidateEntityTypeIsAssignable((IEdmEntityTypeReference) expectedTypeReference, (IEdmEntityTypeReference) targetTypeReference);
                    serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
                    return targetTypeReference;
                }
                case EdmTypeKind.Complex:
                    if (payloadType != null)
                    {
                        VerifyComplexType(expectedTypeReference, payloadType, true);
                    }
                    break;

                case EdmTypeKind.Collection:
                    if ((payloadType != null) && (string.CompareOrdinal(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()) != 0))
                    {
                        VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                        throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_IncompatibleType(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()));
                    }
                    break;

                default:
                    throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);
            return expectedTypeReference;
        }
Esempio n. 29
0
 /// <summary>
 /// Determines if a segment is a complex type.
 /// </summary>
 /// <param name="instance">Segment to be checked.</param>
 /// <param name="parentType">The type of the parent segment.</param>
 /// <returns>True if segment represents a complex type and false otherwise.</returns>
 private static Boolean IsDerivedComplexType(NavigationPropertyToken instance, IEdmType parentType)
 {
     IEdmProperty property = BindProperty(parentType.ToTypeReference(), instance.Name);
     return property.Type.IsODataComplexTypeKind();
 }
Esempio n. 30
0
        /// <summary>
        /// Parses a <paramref name="filter"/> clause on the given <paramref name="elementType"/>, binding
        /// the text into semantic nodes using the provided model.
        /// </summary>
        /// <param name="filter">String representation of the filter expression.</param>
        /// <param name="configuration">The configuration used for binding.</param>
        /// <param name="elementType">Type that the filter clause refers to.</param>
        /// <param name="navigationSource">Navigation source that the elements being filtered are from.</param>
        /// <returns>A <see cref="FilterClause"/> representing the metadata bound filter expression.</returns>
        private FilterClause ParseFilterImplementation(string filter, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource)
        {
            ExceptionUtils.CheckArgumentNotNull(configuration, "configuration");
            ExceptionUtils.CheckArgumentNotNull(elementType, "elementType");
            ExceptionUtils.CheckArgumentNotNull(filter, "filter");

            // Get the syntactic representation of the filter expression
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.FilterLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier);
            QueryToken filterToken = expressionParser.ParseFilter(filter);

            // Bind it to metadata
            BindingState state = new BindingState(configuration);
            state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource);
            state.RangeVariables.Push(state.ImplicitRangeVariable);
            if (applyClause != null)
            {
                state.AggregatedPropertyNames = applyClause.GetLastAggregatedPropertyNames();
            }

            MetadataBinder binder = new MetadataBinder(state);
            FilterBinder filterBinder = new FilterBinder(binder.Bind, state);
            FilterClause boundNode = filterBinder.BindFilter(filterToken);

            return boundNode;
        }
Esempio n. 31
0
        /// <summary>
        /// Convert to collection type reference from element type definition
        /// </summary>
        /// <param name="elementDefinition">The element type definiton</param>
        /// <returns>The collection type reference</returns>
        public static IEdmCollectionTypeReference ToCollectionTypeReference(this IEdmType elementDefinition)
        {
            var elementTypeReference = elementDefinition.ToTypeReference();

            return(elementTypeReference.ToCollectionTypeReference());
        }
Esempio n. 32
0
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationDisabled(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            switch (expectedTypeKind)
            {
                case EdmTypeKind.Entity:
                {
                    if (((payloadType == null) || (expectedTypeKind != payloadType.TypeKind)) || !expectedTypeReference.AsEntity().EntityDefinition().IsAssignableFrom(((IEdmEntityType) payloadType)))
                    {
                        break;
                    }
                    IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
                    serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
                    return targetTypeReference;
                }
                case EdmTypeKind.Complex:
                    if ((payloadType != null) && (expectedTypeKind == payloadType.TypeKind))
                    {
                        VerifyComplexType(expectedTypeReference, payloadType, false);
                    }
                    break;

                case EdmTypeKind.Collection:
                    if ((payloadType != null) && (expectedTypeKind == payloadType.TypeKind))
                    {
                        VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                    }
                    break;

                default:
                    throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, expectedTypeReference);
            return expectedTypeReference;
        }
        /// <summary>
        /// Resolves the payload type versus the expected type and validates that such combination is allowed when strict validation is enabled.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="expectedTypeReference">The expected type reference, or null if no expected type is available.</param>
        /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param>
        /// <returns>The target type reference to use for parsing the value.</returns>
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationEnabled(
            EdmTypeKind expectedTypeKind,
            IEdmTypeReference expectedTypeReference,
            IEdmType payloadType)
        {
            // Strict validation logic
            switch (expectedTypeKind)
            {
                case EdmTypeKind.Complex:
                    if (payloadType != null)
                    {
                        // The payload type must be compatible to the expected type.
                        VerifyComplexType(expectedTypeReference, payloadType, /* failIfNotRelated */ true);

                        // Use the payload type
                        return payloadType.ToTypeReference(/*nullable*/ true);
                    }

                    break;
                case EdmTypeKind.Entity:
                    if (payloadType != null)
                    {
                        // The payload type must be assignable to the expected type.
                        IEdmTypeReference payloadTypeReference = payloadType.ToTypeReference(/*nullable*/ true);
                        ValidationUtils.ValidateEntityTypeIsAssignable((IEdmEntityTypeReference)expectedTypeReference, (IEdmEntityTypeReference)payloadTypeReference);

                        // Use the payload type
                        return payloadTypeReference;
                    }

                    break;
                case EdmTypeKind.Enum:
                    if (payloadType != null && string.CompareOrdinal(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()) != 0)
                    {
                        throw new ODataException(Strings.ValidationUtils_IncompatibleType(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()));
                    }

                    break;
                case EdmTypeKind.Collection:
                    // The type must be exactly equal - note that we intentionally ignore nullability of the items here, since the payload type
                    // can't specify that.
                    if (payloadType != null && !payloadType.IsElementTypeEquivalentTo(expectedTypeReference.Definition))
                    {
                        VerifyCollectionComplexItemType(expectedTypeReference, payloadType);

                        throw new ODataException(Strings.ValidationUtils_IncompatibleType(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()));
                    }

                    break;
                case EdmTypeKind.TypeDefinition:
                    if (payloadType != null && !expectedTypeReference.Definition.IsAssignableFrom(payloadType))
                    {
                        throw new ODataException(Strings.ValidationUtils_IncompatibleType(payloadType.ODataFullName(), expectedTypeReference.ODataFullName()));
                    }

                    break;
                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }

            // Either there's no payload type, in which case use the expected one, or the payload one and the expected one are equal.
            return expectedTypeReference;
        }
Esempio n. 34
0
 private static void VerifyCollectionComplexItemType(IEdmTypeReference expectedTypeReference, IEdmType payloadType)
 {
     IEdmTypeReference collectionItemType = ValidationUtils.ValidateCollectionType(expectedTypeReference).GetCollectionItemType();
     if ((collectionItemType != null) && collectionItemType.IsODataComplexTypeKind())
     {
         IEdmTypeReference typeReference = ValidationUtils.ValidateCollectionType(payloadType.ToTypeReference()).GetCollectionItemType();
         if ((typeReference != null) && typeReference.IsODataComplexTypeKind())
         {
             VerifyComplexType(collectionItemType, typeReference.Definition, false);
         }
     }
 }
        /// <summary>
        /// Resolves the payload type versus the expected type and validates that such combination is allowed when the strict validation is disabled.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="expectedTypeReference">The expected type reference, or null if no expected type is available.</param>
        /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param>
        /// <returns>The target type reference to use for parsing the value.</returns>
        private static IEdmTypeReference ResolveAndValidateTargetTypeStrictValidationDisabled(
            EdmTypeKind expectedTypeKind,
            IEdmTypeReference expectedTypeReference,
            IEdmType payloadType)
        {
            // Lax validation logic
            switch (expectedTypeKind)
            {
                case EdmTypeKind.Complex:
                    // if the expectedTypeKind is different from the payloadType.TypeKind the types are not related 
                    // in any way. In that case we will just use the expected type because we are in lax mode. 
                    if (payloadType != null && expectedTypeKind == payloadType.TypeKind)
                    {
                        // Verify if it's a derived complex type, in all other cases simply use the expected type.
                        VerifyComplexType(expectedTypeReference, payloadType, /* failIfNotRelated */ false);
                        if (EdmLibraryExtensions.IsAssignableFrom(expectedTypeReference.AsComplex().ComplexDefinition(), (IEdmComplexType)payloadType))
                        {
                            return payloadType.ToTypeReference(/*nullable*/ true);
                        }
                    }

                    break;
                case EdmTypeKind.Entity:
                    // if the expectedTypeKind is different from the payloadType.TypeKind the types are not related 
                    // in any way. In that case we will just use the expected type because we are in lax mode. 
                    if (payloadType != null && expectedTypeKind == payloadType.TypeKind)
                    {
                        // If the type is assignable (equal or derived) we will use the payload type, since we want to allow derived entities
                        if (EdmLibraryExtensions.IsAssignableFrom(expectedTypeReference.AsEntity().EntityDefinition(), (IEdmEntityType)payloadType))
                        {
                            IEdmTypeReference payloadTypeReference = payloadType.ToTypeReference(/*nullable*/ true);
                            return payloadTypeReference;
                        }
                    }

                    break;
                case EdmTypeKind.Collection:
                    // if the expectedTypeKind is different from the payloadType.TypeKind the types are not related 
                    // in any way. In that case we will just use the expected type because we are in lax mode. 
                    if (payloadType != null && expectedTypeKind == payloadType.TypeKind)
                    {
                        VerifyCollectionComplexItemType(expectedTypeReference, payloadType);
                    }

                    break;
                case EdmTypeKind.Enum: // enum: no validation

                    break;
                case EdmTypeKind.TypeDefinition: // type definition: no validation

                    break;
                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ReaderValidationUtils_ResolveAndValidateTypeName_Strict_TypeKind));
            }

            // Either there's no payload type, in which case use the expected one, or the payload one and the expected one are equal.
            return expectedTypeReference;
        }
        /// <summary>
        /// Resolves the payload type if there's no expected type.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param>
        /// <returns>The target type reference to use for parsing the value.</returns>
        private static IEdmTypeReference ResolveAndValidateTargetTypeWithNoExpectedType(
            EdmTypeKind expectedTypeKind,
            IEdmType payloadType)
        {
            // No expected type (for example an open property, but other scenarios are possible)
            // We need some type to go on. We do have a model, so we must perform metadata validation and for that we need a type.
            if (payloadType == null)
            {
                if (expectedTypeKind == EdmTypeKind.Entity)
                {
                    throw new ODataException(Strings.ReaderValidationUtils_EntryWithoutType);
                }

                return null; // supports undeclared property
            }

            // Payload types are always nullable.
            IEdmTypeReference payloadTypeReference = payloadType.ToTypeReference(/*nullable*/ true);

            // Use the payload type (since we don't have any other).
            return payloadTypeReference;
        }
        /// <summary>
        /// Resolves the payload type versus the expected type and validates that such combination is allowed.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="expectedTypeReference">The expected type reference, or null if no expected type is available.</param>
        /// <param name="payloadTypeKind">The payload type kind, this may be the one from the type itself, or one detected without resolving the type.</param>
        /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param>
        /// <param name="payloadTypeName">The payload type name, or null if no payload type was specified.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="messageReaderSettings">The message reader settings to use.</param>
        /// <returns>
        /// The target type reference to use for parsing the value.
        /// If there is no user specified model, this will return null.
        /// If there is a user specified model, this method never returns null.
        /// </returns>
        /// <remarks>
        /// This method cannot be used for primitive type resolution. Primitive type resolution is format dependent and format specific methods should be used instead.
        /// </remarks>
        internal static IEdmTypeReference ResolveAndValidateNonPrimitiveTargetType(
            EdmTypeKind expectedTypeKind,
            IEdmTypeReference expectedTypeReference,
            EdmTypeKind payloadTypeKind,
            IEdmType payloadType,
            string payloadTypeName,
            IEdmModel model,
            ODataMessageReaderSettings messageReaderSettings)
        {
            Debug.Assert(messageReaderSettings != null, "messageReaderSettings != null");
            Debug.Assert(
                expectedTypeKind == EdmTypeKind.Enum || expectedTypeKind == EdmTypeKind.Complex || expectedTypeKind == EdmTypeKind.Entity ||
                expectedTypeKind == EdmTypeKind.Collection || expectedTypeKind == EdmTypeKind.TypeDefinition,
                "The expected type kind must be one of Enum, Complex, Entity, Collection or TypeDefinition.");
            Debug.Assert(
                payloadTypeKind == EdmTypeKind.Complex || payloadTypeKind == EdmTypeKind.Entity ||
                payloadTypeKind == EdmTypeKind.Collection || payloadTypeKind == EdmTypeKind.None ||
                payloadTypeKind == EdmTypeKind.Primitive || payloadTypeKind == EdmTypeKind.Enum ||
                payloadTypeKind == EdmTypeKind.TypeDefinition,
                "The payload type kind must be one of None, Primitive, Enum, Complex, Entity, Collection or TypeDefinition.");
            Debug.Assert(
                expectedTypeReference == null || expectedTypeReference.TypeKind() == expectedTypeKind,
                "The expected type kind must match the expected type reference if that is available.");
            Debug.Assert(
                payloadType == null || payloadType.TypeKind == payloadTypeKind,
                "The payload type kind must match the payload type if that is available.");
            Debug.Assert(payloadType == null || payloadTypeName != null, "If we have a payload type, we must have its name as well.");

            bool useExpectedTypeOnlyForTypeResolution = messageReaderSettings.ReaderBehavior.TypeResolver != null && payloadType != null;
            if (!useExpectedTypeOnlyForTypeResolution)
            {
                ValidateTypeSupported(expectedTypeReference);

                // We should validate that the payload type resolved before anything else to produce reasonable error messages
                // Otherwise we might report errors which are somewhat confusing (like "Type '' is Complex but Collection was expected.").
                if (model.IsUserModel() && (expectedTypeReference == null || !messageReaderSettings.DisableStrictMetadataValidation))
                {
                    // When using a type resolver (i.e., useExpectedTypeOnlyForTypeResolution == true) then we don't have to
                    // call this method because the contract with the type resolver is to always resolve the type name and thus
                    // we will always get a defined type.
                    VerifyPayloadTypeDefined(payloadTypeName, payloadType);
                }
            }
            else
            {
                // Payload types are always nullable.
                ValidateTypeSupported(payloadType == null ? null : payloadType.ToTypeReference(/*nullable*/ true));
            }

            // In lax mode don't cross check kinds of types (we would just use the expected type) unless we expect
            // an open property of a specific kind (e.g. top level complex property for PUT requests)
            if (payloadTypeKind != EdmTypeKind.None && (!messageReaderSettings.DisableStrictMetadataValidation || expectedTypeReference == null))
            {
                // Make sure that the type kinds match.
                ValidationUtils.ValidateTypeKind(payloadTypeKind, expectedTypeKind, payloadTypeName);
            }

            if (!model.IsUserModel())
            {
                // If there's no model, it means we should not have the expected type either, and that there's no type to use,
                // no metadata validation to perform.
                Debug.Assert(expectedTypeReference == null, "If we don't have a model, we must not have expected type either.");
                return null;
            }

            if (expectedTypeReference == null || useExpectedTypeOnlyForTypeResolution)
            {
                Debug.Assert(payloadTypeName == null || payloadType != null, "The payload type must have resolved before we get here.");
                return ResolveAndValidateTargetTypeWithNoExpectedType(
                    expectedTypeKind,
                    payloadType);
            }

            if (messageReaderSettings.DisableStrictMetadataValidation)
            {
                return ResolveAndValidateTargetTypeStrictValidationDisabled(
                    expectedTypeKind,
                    expectedTypeReference,
                    payloadType);
            }

            Debug.Assert(payloadTypeName == null || payloadType != null, "The payload type must have resolved before we get here.");
            return ResolveAndValidateTargetTypeStrictValidationEnabled(
                expectedTypeKind,
                expectedTypeReference,
                payloadType);
        }
 /// <summary>
 /// Sets the expected property type for the top-level property.
 /// </summary>
 /// <param name="property">The property instance to set the expected type for.</param>
 /// <param name="dataType">The type to set as the expected property type.</param>
 /// <returns>The <paramref name="property"/> after its expected type was set.</returns>
 public static PropertyInstance ExpectedPropertyType(this PropertyInstance property, IEdmType dataType, bool nullable = false)
 {
     ExceptionUtilities.CheckArgumentNotNull(property, "property");
     ODataPayloadElementExtensions.AddExpectedTypeAnnotation(property).EdmExpectedType = dataType.ToTypeReference(nullable);
     return(property);
 }
Esempio n. 39
0
 internal static IEdmTypeReference ResolveAndValidateNonPrimitiveTargetType(EdmTypeKind expectedTypeKind, IEdmTypeReference expectedTypeReference, EdmTypeKind payloadTypeKind, IEdmType payloadType, string payloadTypeName, IEdmModel model, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
 {
     bool flag = (messageReaderSettings.ReaderBehavior.TypeResolver != null) && (payloadType != null);
     if (!flag)
     {
         ValidateTypeSupported(expectedTypeReference, version);
         if (model.IsUserModel() && ((expectedTypeReference == null) || !messageReaderSettings.DisableStrictMetadataValidation))
         {
             VerifyPayloadTypeDefined(payloadTypeName, payloadType);
         }
     }
     else
     {
         ValidateTypeSupported((payloadType == null) ? null : payloadType.ToTypeReference(true), version);
     }
     if ((payloadTypeKind != EdmTypeKind.None) && (!messageReaderSettings.DisableStrictMetadataValidation || (expectedTypeReference == null)))
     {
         ValidationUtils.ValidateTypeKind(payloadTypeKind, expectedTypeKind, payloadTypeName);
     }
     serializationTypeNameAnnotation = null;
     if (!model.IsUserModel())
     {
         return null;
     }
     if ((expectedTypeReference == null) || flag)
     {
         return ResolveAndValidateTargetTypeWithNoExpectedType(expectedTypeKind, payloadType, payloadTypeName, out serializationTypeNameAnnotation);
     }
     if (messageReaderSettings.DisableStrictMetadataValidation)
     {
         return ResolveAndValidateTargetTypeStrictValidationDisabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation);
     }
     return ResolveAndValidateTargetTypeStrictValidationEnabled(expectedTypeKind, expectedTypeReference, payloadType, payloadTypeName, out serializationTypeNameAnnotation);
 }
 /// <summary>
 /// Sets the expected item type for the top-level collection.
 /// </summary>
 /// <typeparam name="T">The acutal collection type, i.e., a primitive or a complex collection type.</typeparam>
 /// <param name="collection">The collection instance to set the expected item type for.</param>
 /// <param name="dataType">The type to set as the expected item type.</param>
 /// <returns>The <paramref name="collection"/> after its expected type was set.</returns>
 public static T ExpectedCollectionItemType <T>(this T collection, IEdmType dataType, bool nullable = true) where T : ODataPayloadElementCollection
 {
     ExceptionUtilities.CheckArgumentNotNull(collection, "collection");
     AddExpectedTypeAnnotation(collection).EdmExpectedType = dataType.ToTypeReference(nullable);
     return(collection);
 }
Esempio n. 41
0
        /// <summary>
        /// Resolve a type name against the provided <paramref name="model"/>. If not payload type name is specified,
        /// derive the type from the model type (if available).
        /// </summary>
        /// <param name="model">The model to use.</param>
        /// <param name="typeReferenceFromMetadata">The type inferred from the model or null if the model is not a user model.</param>
        /// <param name="collectionValue">The value in question to resolve the type for.</param>
        /// <param name="isOpenPropertyType">True if the type name belongs to an open property.</param>
        /// <param name="writerValidator">The writer validator to use for validation.</param>
        /// <returns>A type for the <paramref name="collectionValue"/> or null if no type name is specified and no metadata is available.</returns>
        internal static IEdmTypeReference ResolveAndValidateTypeForCollectionValue(IEdmModel model, IEdmTypeReference typeReferenceFromMetadata, ODataCollectionValue collectionValue, bool isOpenPropertyType, IWriterValidator writerValidator)
        {
            Debug.Assert(model != null, "model != null");

            var typeName = collectionValue.TypeName;

            ValidateIfTypeNameMissing(typeName, model, isOpenPropertyType);

            IEdmType typeFromValue = typeName == null ? null : ResolveAndValidateTypeName(model, typeName, EdmTypeKind.Collection, false, writerValidator);

            if (typeReferenceFromMetadata != null)
            {
                writerValidator.ValidateTypeKind(EdmTypeKind.Collection, typeReferenceFromMetadata.TypeKind(), false, typeFromValue);
            }

            IEdmTypeReference typeReferenceFromValue = ResolveTypeFromMetadataAndValue(typeReferenceFromMetadata, typeFromValue == null ? null : typeFromValue.ToTypeReference(), writerValidator);

            if (typeReferenceFromValue != null)
            {
                // update nullability from metadata
                if (typeReferenceFromMetadata != null)
                {
                    typeReferenceFromValue = typeReferenceFromMetadata;
                }

                // validate that the collection type represents a valid Collection type (e.g., is unordered).
                typeReferenceFromValue = ValidationUtils.ValidateCollectionType(typeReferenceFromValue);
            }

            return(typeReferenceFromValue);
        }
Esempio n. 42
0
 /// <summary>
 /// Gets the nullable type reference for a payload type; if the payload type is null, uses Edm.String.
 /// </summary>
 /// <param name="payloadType">The payload type to get the type reference for.</param>
 /// <returns>The nullable <see cref="IEdmTypeReference"/> for the <paramref name="payloadType"/>.</returns>
 internal static IEdmTypeReference GetNullablePayloadTypeReference(IEdmType payloadType)
 {
     return(payloadType == null ? null : payloadType.ToTypeReference(true));
 }
        /// <summary>
        /// Resolves the payload type if there's no expected type.
        /// </summary>
        /// <param name="expectedTypeKind">The expected type kind for the value.</param>
        /// <param name="payloadType">The payload type, or null if the payload type was not specified, or it didn't resolve against the model.</param>
        /// <param name="payloadTypeName">The payload type name, or null if no payload type was specified.</param>
        /// <param name="serializationTypeNameAnnotation">Potentially non-null instance of an annotation to put on the value reported from the reader.</param>
        /// <returns>The target type reference to use for parsing the value.</returns>
        private static IEdmTypeReference ResolveAndValidateTargetTypeWithNoExpectedType(
            EdmTypeKind expectedTypeKind,
            IEdmType payloadType,
            string payloadTypeName,
            out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            Debug.Assert(payloadTypeName == null || payloadType != null, "The payload type must have resolved before we get here.");
            serializationTypeNameAnnotation = null;

            // No expected type (for example an open property, but other scenarios are possible)
            // We need some type to go on. We do have a model, so we must perform metadata validation and for that we need a type.
            if (payloadType == null)
            {
                if (expectedTypeKind == EdmTypeKind.Entity)
                {
                    throw new ODataException(Strings.ReaderValidationUtils_EntryWithoutType);
                }

                throw new ODataException(Strings.ReaderValidationUtils_ValueWithoutType);
            }

            // Payload types are always nullable.
            IEdmTypeReference payloadTypeReference = payloadType.ToTypeReference(/*nullable*/ true);
            serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, payloadTypeReference);

            // Use the payload type (since we don't have any other).
            return payloadTypeReference;
        }
Esempio n. 44
0
 /// <summary>
 /// Gets the nullable type reference for a payload type; if the payload type is null, uses Edm.String.
 /// </summary>
 /// <param name="payloadType">The payload type to get the type reference for.</param>
 /// <returns>The nullable <see cref="IEdmTypeReference"/> for the <paramref name="payloadType"/>.</returns>
 internal static IEdmTypeReference GetNullablePayloadTypeReference(IEdmType payloadType)
 {
     return payloadType == null ? null : payloadType.ToTypeReference(true);
 }
Esempio n. 45
0
 private static IEdmTypeReference ResolveAndValidateTargetTypeWithNoExpectedType(EdmTypeKind expectedTypeKind, IEdmType payloadType, string payloadTypeName, out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
 {
     serializationTypeNameAnnotation = null;
     if (payloadType == null)
     {
         if (expectedTypeKind == EdmTypeKind.Entity)
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_EntryWithoutType);
         }
         throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_ValueWithoutType);
     }
     IEdmTypeReference targetTypeReference = payloadType.ToTypeReference(true);
     serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
     return targetTypeReference;
 }
Esempio n. 46
0
        /// <summary>
        /// Parses an <paramref name="apply"/> clause on the given <paramref name="elementType"/>, binding
        /// the text into a metadata-bound or dynamic properties to be applied using the provided model.
        /// </summary>
        /// <param name="apply">String representation of the apply expression.</param>
        /// <param name="configuration">The configuration used for binding.</param>
        /// <param name="elementType">Type that the apply clause refers to.</param>
        /// <param name="navigationSource">Navigation source that the elements being filtered are from.</param>
        /// <returns>A <see cref="ApplyClause"/> representing the metadata bound apply expression.</returns>
        private static ApplyClause ParseApplyImplementation(string apply, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource)
        {
            ExceptionUtils.CheckArgumentNotNull(configuration, "configuration");
            ExceptionUtils.CheckArgumentNotNull(elementType, "elementType");
            ExceptionUtils.CheckArgumentNotNull(apply, "apply");

            // Get the syntactic representation of the apply expression
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.FilterLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier);
            var applyTokens = expressionParser.ParseApply(apply);

            // Bind it to metadata
            BindingState state = new BindingState(configuration);
            state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource);
            state.RangeVariables.Push(state.ImplicitRangeVariable);
            MetadataBinder binder = new MetadataBinder(state);
            ApplyBinder applyBinder = new ApplyBinder(binder.Bind, state);
            ApplyClause boundNode = applyBinder.BindApply(applyTokens);

            return boundNode;
        }
Esempio n. 47
0
        /// <summary>
        /// Parses an <paramref name="orderBy "/> clause on the given <paramref name="elementType"/>, binding
        /// the text into semantic nodes using the provided model.
        /// </summary>
        /// <param name="orderBy">String representation of the orderby expression.</param>
        /// <param name="configuration">The configuration used for binding.</param>
        /// <param name="elementType">Type that the orderby clause refers to.</param>
        /// <param name="navigationSource">NavigationSource that the elements are from.</param>
        /// <returns>An <see cref="OrderByClause"/> representing the metadata bound orderby expression.</returns>
        private OrderByClause ParseOrderByImplementation(string orderBy, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource)
        {
            ExceptionUtils.CheckArgumentNotNull(configuration, "configuration");
            ExceptionUtils.CheckArgumentNotNull(configuration.Model, "model");
            ExceptionUtils.CheckArgumentNotNull(elementType, "elementType");
            ExceptionUtils.CheckArgumentNotNull(orderBy, "orderBy");

            // Get the syntactic representation of the orderby expression
            UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.OrderByLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier);
            var orderByQueryTokens = expressionParser.ParseOrderBy(orderBy);

            // Bind it to metadata
            BindingState state = new BindingState(configuration);
            state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource);
            state.RangeVariables.Push(state.ImplicitRangeVariable);
            if (applyClause != null)
            {
                state.AggregatedPropertyNames = applyClause.GetLastAggregatedPropertyNames();
            }

            MetadataBinder binder = new MetadataBinder(state);
            OrderByBinder orderByBinder = new OrderByBinder(binder.Bind);
            OrderByClause orderByClause = orderByBinder.BindOrderBy(state, orderByQueryTokens);

            return orderByClause;
        }
Esempio n. 48
0
        /// <summary>
        /// Generate a select item <see cref="SelectItem"/> based on a <see cref="SelectTermToken"/>.
        /// for example:  abc/efg($count=true;$filter=....;$top=1)
        /// </summary>
        /// <param name="tokenIn">the select term token to visit</param>
        /// <returns>the select item for this select term token.</returns>
        private SelectItem GenerateSelectItem(SelectTermToken tokenIn)
        {
            ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn");
            ExceptionUtils.CheckArgumentNotNull(tokenIn.PathToProperty, "pathToProperty");

            VerifySelectedPath(tokenIn);

            SelectItem newSelectItem;

            if (ProcessWildcardTokenPath(tokenIn, out newSelectItem))
            {
                return(newSelectItem);
            }

            IList <ODataPathSegment> selectedPath = ProcessSelectTokenPath(tokenIn.PathToProperty);

            Debug.Assert(selectedPath.Count > 0);

            // Navigation property should be the last segment in select path.
            if (VerifySelectedNavigationProperty(selectedPath, tokenIn))
            {
                return(new PathSelectItem(new ODataSelectPath(selectedPath)));
            }

            // We should use the "NavigationSource" at this level for the next level binding.
            IEdmNavigationSource targetNavigationSource = this.NavigationSource;
            ODataPathSegment     lastSegment            = selectedPath.Last();
            IEdmType             targetElementType      = lastSegment.TargetEdmType;
            IEdmCollectionType   collection             = targetElementType as IEdmCollectionType;

            if (collection != null)
            {
                targetElementType = collection.ElementType.Definition;
            }
            IEdmTypeReference elementTypeReference = targetElementType.ToTypeReference();

            // $compute
            ComputeClause          compute             = BindCompute(tokenIn.ComputeOption, targetNavigationSource, elementTypeReference);
            HashSet <EndPathToken> generatedProperties = GetGeneratedProperties(compute, null);

            // $filter
            FilterClause filter = BindFilter(tokenIn.FilterOption, targetNavigationSource, elementTypeReference, generatedProperties);

            // $orderby
            OrderByClause orderBy = BindOrderby(tokenIn.OrderByOptions, targetNavigationSource, elementTypeReference, generatedProperties);

            // $search
            SearchClause search = BindSearch(tokenIn.SearchOption, targetNavigationSource, elementTypeReference);

            // $select
            List <ODataPathSegment> parsedPath = new List <ODataPathSegment>(this.parsedSegments);

            parsedPath.AddRange(selectedPath);
            SelectExpandClause selectExpand = BindSelectExpand(null, tokenIn.SelectOption, parsedPath, targetNavigationSource, elementTypeReference, generatedProperties);

            return(new PathSelectItem(new ODataSelectPath(selectedPath),
                                      targetNavigationSource,
                                      selectExpand,
                                      filter,
                                      orderBy,
                                      tokenIn.TopOption,
                                      tokenIn.SkipOption,
                                      tokenIn.CountQueryOption,
                                      search,
                                      compute));
        }
Esempio n. 49
0
 internal static IEdmCollectionType GetCollectionType(IEdmType itemType)
 {
     if (!itemType.IsODataPrimitiveTypeKind() && !itemType.IsODataComplexTypeKind())
     {
         throw new ODataException(Microsoft.Data.OData.Strings.EdmLibraryExtensions_CollectionItemCanBeOnlyPrimitiveOrComplex);
     }
     return new EdmCollectionType(itemType.ToTypeReference());
 }