private static UnboundFunctionPathSegment TryMatchUnboundFunctionCall(string segment, Queue <string> segments, IEdmModel model) { IEdmEntityContainer container = ExtractEntityContainer(model); string nextSegment = segments.Count > 0 ? segments.Peek() : null; IEnumerable <IEdmOperationImport> operationImports = container.FindMatchedOperationImports(segment); IEnumerable <IEdmFunctionImport> possibleFunctions = operationImports.OfType <IEdmFunctionImport>(); UnboundFunctionPathSegment unboundFunctionSegment = FunctionResolver.TryResolveUnbound(possibleFunctions, model, nextSegment); if (unboundFunctionSegment != null && FunctionResolver.IsEnclosedInParentheses(nextSegment)) { segments.Dequeue(); } return(unboundFunctionSegment); }
private static BoundFunctionPathSegment TryMatchBoundFunctionCall(string segment, Queue <string> segments, IEdmModel model, IEdmType bindingType) { Contract.Assert(model != null); Contract.Assert(bindingType != null); string nextSegment = segments.Count > 0 ? segments.Peek() : null; IEnumerable <IEdmOperation> matchedOperations = model.FindMatchedOperations(segment, bindingType); IEnumerable <IEdmFunction> possibleFunctions = matchedOperations.OfType <IEdmFunction>(); if (possibleFunctions.Count() == 0) { return(null); } IEdmEntityType currentBindingType; if (bindingType.TypeKind == EdmTypeKind.Collection) { currentBindingType = (IEdmEntityType)(((IEdmCollectionType)bindingType).ElementType.Definition); } else { currentBindingType = (IEdmEntityType)bindingType; } while (currentBindingType != null) { IEnumerable <IEdmFunction> matchedFunctions = possibleFunctions.Where(f => FunctionResolver.IsBoundTo(f, currentBindingType)); BoundFunctionPathSegment functionSegment = FunctionResolver.TryResolveBound(matchedFunctions, model, nextSegment); if (functionSegment != null) { if (FunctionResolver.IsEnclosedInParentheses(nextSegment)) { segments.Dequeue(); } return(functionSegment); } currentBindingType = currentBindingType.BaseEntityType(); } return(null); }
/// <summary> /// Parses the specified OData path as an <see cref="ODataPath"/> that contains additional information about the EDM type and entity set for the path. /// </summary> /// <param name="model">The model to use for path parsing.</param> /// <param name="odataPath">The OData path to parse.</param> /// <returns>A parsed representation of the path, or <c>null</c> if the path does not match the model.</returns> public virtual ODataPath Parse(IEdmModel model, string odataPath) { if (model == null) { throw Error.ArgumentNull("model"); } if (odataPath == null) { throw Error.ArgumentNull("odataPath"); } List <ODataPathSegment> pathSegments = new List <ODataPathSegment>(); ODataPathSegment pathSegment = null; IEdmType previousEdmType = null; Queue <string> segments = new Queue <string>(ParseSegments(odataPath)); while (segments.Count > 0) { string nextSegment = segments.Dequeue(); // ignore empty parenthesis if (FunctionResolver.IsEnclosedInParentheses(nextSegment) && String.IsNullOrWhiteSpace(nextSegment.Substring(1, nextSegment.Length - 2))) { continue; } pathSegment = ParseNextSegment(model, pathSegment, previousEdmType, nextSegment, segments); // If the Uri stops matching the model at any point, return null if (pathSegment == null) { return(null); } pathSegments.Add(pathSegment); previousEdmType = pathSegment.GetEdmType(previousEdmType); } return(new ODataPath(pathSegments)); }