Пример #1
0
        /// <summary>
        /// Returns the type of the property on the specified type.
        /// </summary>
        /// <param name="type">The type to look for the property on.</param>
        /// <param name="propertyName">The name of the property to look for.</param>
        /// <returns>The type of the property specified.</returns>
        private static IEdmTypeReference GetPropertyType(IEdmType type, string propertyName)
        {
            Debug.Assert(propertyName != null, "propertyName != null");

            IEdmStructuredType structuredType = type as IEdmStructuredType;
            IEdmProperty       property       = structuredType == null ? null : structuredType.FindProperty(propertyName);

            if (property != null)
            {
                IEdmTypeReference propertyType = property.Type;
                if (propertyType.IsNonEntityCollectionType())
                {
                    throw new ODataException(ODataErrorStrings.EpmSourceTree_CollectionPropertyCannotBeMapped(propertyName, type.ODataFullName()));
                }

                if (propertyType.IsStream())
                {
                    throw new ODataException(ODataErrorStrings.EpmSourceTree_StreamPropertyCannotBeMapped(propertyName, type.ODataFullName()));
                }

                if (propertyType.IsSpatial())
                {
                    throw new ODataException(ODataErrorStrings.EpmSourceTree_SpatialTypeCannotBeMapped(propertyName, type.ODataFullName()));
                }

                return(property.Type);
            }

            if (type != null && !type.IsOpenType())
            {
                throw new ODataException(ODataErrorStrings.EpmSourceTree_MissingPropertyOnType(propertyName, type.ODataFullName()));
            }

            return(null);
        }
Пример #2
0
        private static IEdmTypeReference GetPropertyType(IEdmType type, string propertyName)
        {
            IEdmStructuredType type2    = type as IEdmStructuredType;
            IEdmProperty       property = (type2 == null) ? null : type2.FindProperty(propertyName);

            if (property != null)
            {
                IEdmTypeReference typeReference = property.Type;
                if (typeReference.IsNonEntityODataCollectionTypeKind())
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_CollectionPropertyCannotBeMapped(propertyName, type.ODataFullName()));
                }
                if (typeReference.IsStream())
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_StreamPropertyCannotBeMapped(propertyName, type.ODataFullName()));
                }
                if (typeReference.IsSpatial())
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_SpatialTypeCannotBeMapped(propertyName, type.ODataFullName()));
                }
                return(property.Type);
            }
            if ((type != null) && !type.IsOpenType())
            {
                throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_MissingPropertyOnType(propertyName, type.ODataFullName()));
            }
            return(null);
        }
Пример #3
0
        internal static bool ResolveOperationFromList(string identifier, IEnumerable <string> parameterNames, IEdmType bindingType, IEdmModel model, out IEdmOperation matchingOperation, ODataUriResolver resolver)
        {
            // TODO: update code that is duplicate between operation and operation import, add more tests.
            // If the previous segment is an open type, the service action name is required to be fully qualified or else we always treat it as an open property name.
            if (bindingType != null)
            {
                // TODO: look up actual container names here?
                // When using extension, there may be function call with unqualified name. So loose the restriction here.
                if (bindingType.IsOpenType() && !identifier.Contains(".") && resolver.GetType() == typeof(ODataUriResolver))
                {
                    matchingOperation = null;
                    return(false);
                }
            }

            IList <IEdmOperation> candidateMatchingOperations = null;

            // The extension method FindBoundOperations & FindOperations call IEdmModel.FindDeclaredBoundOperations which can be implemented by anyone and it could throw any type of exception
            // so catching all of them and simply putting it in the inner exception.
            try
            {
                if (bindingType != null)
                {
                    candidateMatchingOperations = resolver.ResolveBoundOperations(model, identifier, bindingType).ToList();
                }
                else
                {
                    candidateMatchingOperations = resolver.ResolveUnboundOperations(model, identifier).ToList();
                }
            }
            catch (Exception exc)
            {
                if (ExceptionUtils.IsCatchableExceptionType(exc))
                {
                    throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_FoundInvalidOperation(identifier), exc);
                }

                throw;
            }

            IList <IEdmAction> foundActionsWhenLookingForFunctions = new List <IEdmAction>();
            int parameterNamesCount = parameterNames.Count();

            if (bindingType != null)
            {
                candidateMatchingOperations = candidateMatchingOperations.EnsureOperationsBoundWithBindingParameter().ToList();
            }

            // If the number of parameters > 0 then this has to be a function as actions can't have parameters on the uri only in the payload. Filter further by parameters in this case, otherwise don't.
            if (parameterNamesCount > 0)
            {
                // can only be a function as only functions have parameters on the uri.
                candidateMatchingOperations = candidateMatchingOperations.RemoveActions(out foundActionsWhenLookingForFunctions).FilterFunctionsByParameterNames(parameterNames, resolver.EnableCaseInsensitive).Cast <IEdmOperation>().ToList();
            }
            else if (bindingType != null)
            {
                // Filter out functions with more than one parameter. Actions should not be filtered as the parameters are in the payload not the uri
                candidateMatchingOperations = candidateMatchingOperations.Where(o => (o.IsFunction() && o.Parameters.Count() == 1) || o.IsAction()).ToList();
            }
            else
            {
                // Filter out functions with any parameters
                candidateMatchingOperations = candidateMatchingOperations.Where(o => (o.IsFunction() && !o.Parameters.Any()) || o.IsAction()).ToList();
            }

            // Only filter if there is more than one and its needed.
            if (candidateMatchingOperations.Count > 1)
            {
                candidateMatchingOperations = candidateMatchingOperations.FilterBoundOperationsWithSameTypeHierarchyToTypeClosestToBindingType(bindingType).ToList();
            }

            // If any of the things returned are an action, it better be the only thing returned, and there can't be parameters in the URL
            if (candidateMatchingOperations.Any(f => f.IsAction()))
            {
                if (candidateMatchingOperations.Count > 1)
                {
                    if (candidateMatchingOperations.Any(o => o.IsFunction()))
                    {
                        throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleOperationOverloads(identifier));
                    }
                    else
                    {
                        throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleActionOverloads(identifier));
                    }
                }

                if (parameterNames.Count() != 0)
                {
                    throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier));
                }

                matchingOperation = candidateMatchingOperations.Single();
                return(true);
            }

            if (foundActionsWhenLookingForFunctions.Count > 0)
            {
                throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier));
            }

            if (candidateMatchingOperations.Count > 1)
            {
                throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_NoSingleMatchFound(identifier, string.Join(",", parameterNames.ToArray())));
            }

            matchingOperation = candidateMatchingOperations.SingleOrDefault();
            return(matchingOperation != null);
        }
Пример #4
0
        /// <summary>
        /// Try to resolve a function from the given inputs.
        /// </summary>
        /// <param name="identifier">The identifier of the function that we're trying to find</param>
        /// <param name="parameterNames">the names of the parameters to search for.</param>
        /// <param name="bindingType">the type of the previous segment</param>
        /// <param name="model">the model to use to look up the function import</param>
        /// <param name="matchingFunctionImport">The single matching function found.</param>
        /// <returns>True if a function was matched, false otherwise. Will throw if the model has illegal function imports.</returns>
        internal static bool ResolveFunctionsFromList(string identifier, IList <string> parameterNames, IEdmType bindingType, IEdmModel model, out IEdmFunctionImport matchingFunctionImport)
        {
            DebugUtils.CheckNoExternalCallers();

            // If the previous segment is an open type, the service action name is required to be fully qualified or else we always treat it as an open property name.
            if (bindingType != null)
            {
                // TODO: look up actual container names here?
                if (bindingType.IsOpenType() && !identifier.Contains("."))
                {
                    matchingFunctionImport = null;
                    return(false);
                }
            }

            // if the model implements the extensions interface, then leave resolution entirely up to the user.
            var extendedModel = model as IODataUriParserModelExtensions;

            if (extendedModel != null)
            {
                matchingFunctionImport = extendedModel.FindFunctionImportByBindingParameterType(bindingType, identifier, parameterNames);
                if (matchingFunctionImport == null)
                {
                    return(false);
                }

                return(true);
            }

            // Get all the possible functions by name and binding type
            // For this method to end up NOT throwing, this call must return a single action or 1 or more functions
            IList <IEdmFunctionImport> functionImports = model.FindFunctionImportsBySpecificBindingParameterType(bindingType, identifier).ToList();

            if (functionImports.Count == 0)
            {
                matchingFunctionImport = null;
                return(false);
            }

            Debug.Assert(functionImports != null && functionImports.Count > 0, "Should have returned at least one function import to get here.");
            Debug.Assert(functionImports.All(f => f.Name == identifier.Split('.').Last()), "list of possible functions must have same name as identifier");

            if (!functionImports.AllHaveEqualReturnTypeAndAttributes())
            {
                throw new ODataException(ODataErrorStrings.RequestUriProcessor_FoundInvalidFunctionImport(identifier));
            }

            // If any of the things returned are an action, it better be the only thing returned, and there can't be parameters in the URL
            if (functionImports.Any(f => f.IsSideEffecting))
            {
                if (functionImports.Count > 1)
                {
                    throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleActionOverloads(identifier));
                }

                if (parameterNames.Count() != 0)
                {
                    throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier));
                }

                matchingFunctionImport = functionImports.Single();
                return(true);
            }

            // Functions - resolve overloads as needed
            matchingFunctionImport = ResolveOverloadsByParameterNames(functionImports, parameterNames, identifier);
            return(matchingFunctionImport != null);
        }
        internal static bool ResolveOperationFromList(string identifier, IEnumerable<string> parameterNames, IEdmType bindingType, IEdmModel model, out IEdmOperation matchingOperation, ODataUriResolver resolver)
        {
            // TODO: update code that is duplicate between operation and operation import, add more tests.
            // If the previous segment is an open type, the service action name is required to be fully qualified or else we always treat it as an open property name.
            if (bindingType != null)
            {
                // TODO: look up actual container names here?
                if (bindingType.IsOpenType() && !identifier.Contains("."))
                {
                    matchingOperation = null;
                    return false;
                }
            }

            IList<IEdmOperation> candidateMatchingOperations = null;

            // The extension method FindBoundOperations & FindOperations call IEdmModel.FindDeclaredBoundOperations which can be implemented by anyone and it could throw any type of exception
            // so catching all of them and simply putting it in the inner exception.
            try
            {
                if (bindingType != null)
                {
                    candidateMatchingOperations = resolver.ResolveBoundOperations(model, identifier, bindingType).ToList();
                }
                else
                {
                    candidateMatchingOperations = resolver.ResolveUnboundOperations(model, identifier).ToList();
                }
            }
            catch (Exception exc)
            {
                if (ExceptionUtils.IsCatchableExceptionType(exc))
                {
                    throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_FoundInvalidOperation(identifier), exc);
                }

                throw;
            }

            IList<IEdmAction> foundActionsWhenLookingForFunctions = new List<IEdmAction>();
            int parameterNamesCount = parameterNames.Count();

            if (bindingType != null)
            {
                candidateMatchingOperations = candidateMatchingOperations.EnsureOperationsBoundWithBindingParameter().ToList();
            }

            // If the number of parameters > 0 then this has to be a function as actions can't have parameters on the uri only in the payload. Filter further by parameters in this case, otherwise don't.
            if (parameterNamesCount > 0)
            {
                // can only be a function as only functions have parameters on the uri.
                candidateMatchingOperations = candidateMatchingOperations.RemoveActions(out foundActionsWhenLookingForFunctions).FilterFunctionsByParameterNames(parameterNames, resolver.EnableCaseInsensitive).Cast<IEdmOperation>().ToList();
            }
            else if (bindingType != null)
            {
                // Filter out functions with more than one parameter. Actions should not be filtered as the parameters are in the payload not the uri
                candidateMatchingOperations = candidateMatchingOperations.Where(o => (o.IsFunction() && o.Parameters.Count() == 1) || o.IsAction()).ToList();
            }
            else
            {
                // Filter out functions with any parameters
                candidateMatchingOperations = candidateMatchingOperations.Where(o => (o.IsFunction() && !o.Parameters.Any()) || o.IsAction()).ToList();
            }

            // Only filter if there is more than one and its needed.
            if (candidateMatchingOperations.Count > 1)
            {
                candidateMatchingOperations = candidateMatchingOperations.FilterBoundOperationsWithSameTypeHierarchyToTypeClosestToBindingType(bindingType).ToList();
            }

            // If any of the things returned are an action, it better be the only thing returned, and there can't be parameters in the URL
            if (candidateMatchingOperations.Any(f => f.IsAction()))
            {
                if (candidateMatchingOperations.Count > 1)
                {
                    if (candidateMatchingOperations.Any(o => o.IsFunction()))
                    {
                        throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleOperationOverloads(identifier));
                    }
                    else
                    {
                        throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleActionOverloads(identifier));
                    }
                }

                if (parameterNames.Count() != 0)
                {
                    throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier));
                }

                matchingOperation = candidateMatchingOperations.Single();
                return true;
            }

            if (foundActionsWhenLookingForFunctions.Count > 0)
            {
                throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier));
            }

            if (candidateMatchingOperations.Count > 1)
            {
                throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_NoSingleMatchFound(identifier, string.Join(",", parameterNames.ToArray())));
            }

            matchingOperation = candidateMatchingOperations.SingleOrDefault();
            return matchingOperation != null;
        }
Пример #6
0
        /// <summary>
        /// Returns the type of the property on the specified type.
        /// </summary>
        /// <param name="type">The type to look for the property on.</param>
        /// <param name="propertyName">The name of the property to look for.</param>
        /// <returns>The type of the property specified.</returns>
        private static IEdmTypeReference GetPropertyType(IEdmType type, string propertyName)
        {
            Debug.Assert(propertyName != null, "propertyName != null");

            IEdmStructuredType structuredType = type as IEdmStructuredType;
            IEdmProperty property = structuredType == null ? null : structuredType.FindProperty(propertyName);

            if (property != null)
            {
                IEdmTypeReference propertyType = property.Type;
                if (propertyType.IsNonEntityODataCollectionTypeKind())
                {
                    throw new ODataException(o.Strings.EpmSourceTree_CollectionPropertyCannotBeMapped(propertyName, type.ODataFullName()));
                }
                
                if (propertyType.IsStream())
                {
                    throw new ODataException(o.Strings.EpmSourceTree_StreamPropertyCannotBeMapped(propertyName, type.ODataFullName()));
                }
                
                if (propertyType.IsSpatial())
                {
                    throw new ODataException(o.Strings.EpmSourceTree_SpatialTypeCannotBeMapped(propertyName, type.ODataFullName()));
                }
                
                return property.Type;
            }

            if (type != null && !type.IsOpenType())
            {
                throw new ODataException(o.Strings.EpmSourceTree_MissingPropertyOnType(propertyName, type.ODataFullName()));
            }

            return null;
        }
Пример #7
0
 private static IEdmTypeReference GetPropertyType(IEdmType type, string propertyName)
 {
     IEdmStructuredType type2 = type as IEdmStructuredType;
     IEdmProperty property = (type2 == null) ? null : type2.FindProperty(propertyName);
     if (property != null)
     {
         IEdmTypeReference typeReference = property.Type;
         if (typeReference.IsNonEntityODataCollectionTypeKind())
         {
             throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_CollectionPropertyCannotBeMapped(propertyName, type.ODataFullName()));
         }
         if (typeReference.IsStream())
         {
             throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_StreamPropertyCannotBeMapped(propertyName, type.ODataFullName()));
         }
         if (typeReference.IsSpatial())
         {
             throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_SpatialTypeCannotBeMapped(propertyName, type.ODataFullName()));
         }
         return property.Type;
     }
     if ((type != null) && !type.IsOpenType())
     {
         throw new ODataException(Microsoft.Data.OData.Strings.EpmSourceTree_MissingPropertyOnType(propertyName, type.ODataFullName()));
     }
     return null;
 }