/// <summary>
        /// Builds a URI with the given type name appended as a new segment on the base URI.
        /// </summary>
        /// <param name="baseUri">The URI to append to.</param>
        /// <param name="typeName">The fully qualified type name to append.</param>
        /// <returns>The URI with the type segment appended.</returns>
        internal override Uri AppendTypeSegment(Uri baseUri, string typeName)
        {
            ValidateBaseUri(baseUri);
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(typeName, "typeName");

            return(AppendSegment(baseUri, typeName, true /*escapeSegment*/));
        }
        /// <summary>
        /// Builds the navigation link for the navigation property.
        /// </summary>
        /// <param name="baseUri">The URI to append to.</param>
        /// <param name="navigationPropertyName">The name of the navigation property to get the navigation link URI for.</param>
        /// <returns>The navigation link URI for the navigation property.</returns>
        internal override Uri BuildNavigationLinkUri(Uri baseUri, string navigationPropertyName)
        {
            ValidateBaseUri(baseUri);
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(navigationPropertyName, "navigationPropertyName");

            return(AppendSegment(baseUri, navigationPropertyName, true /*escapeSegment*/));
        }
예제 #3
0
        /// <summary>
        /// Add a custom uri function to extend uri functions.
        /// In case the function name already exists as a custom function, the signature will be added as an another overload.
        /// </summary>
        /// <param name="functionName">The new custom function name</param>
        /// <param name="functionSignature">The new custom function signature</param>
        /// <exception cref="ArgumentNullException">Arguments are null, or function signature return type is null</exception>
        /// <exception cref="ODataException">Throws if built-in function name already exists.</exception>
        /// <exception cref="ODataException">Throws if built-in function signature overload already exists.</exception>
        /// <exception cref="ODataException">Throws if custom function signature overload already exists</exception>
        public static void AddCustomUriFunction(string functionName, FunctionSignatureWithReturnType functionSignature)
        {
            // Parameters validation
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(functionName, "customFunctionName");
            ExceptionUtils.CheckArgumentNotNull(functionSignature, "newCustomFunctionSignature");

            ValidateFunctionWithReturnType(functionSignature);

            // Thread saftey - before using the custom functions dictionary
            lock (Locker)
            {
                // Check if the function does already exists in the Built-In functions
                // If 'addAsOverloadToBuiltInFunction' parameter is false - throw expection
                // Else, add as a custom function
                FunctionSignatureWithReturnType[] existingBuiltInFunctionOverload;
                if (BuiltInUriFunctions.TryGetBuiltInFunction(functionName, out existingBuiltInFunctionOverload))
                {
                    // Function name exists, check if full signature exists among the overloads.
                    if (existingBuiltInFunctionOverload.Any(builtInFunction =>
                                                            AreFunctionsSignatureEqual(functionSignature, builtInFunction)))
                    {
                        throw new ODataException(Strings.CustomUriFunctions_AddCustomUriFunction_BuiltInExistsFullSignature(functionName));
                    }
                }

                AddCustomFunction(functionName, functionSignature);
            }
        }
        /// <summary>
        /// Builds the URI for an entity set.
        /// </summary>
        /// <param name="baseUri">The URI to append to.</param>
        /// <param name="entitySetName">The entity set name.</param>
        /// <returns>The entity set URI.</returns>
        internal override Uri BuildEntitySetUri(Uri baseUri, string entitySetName)
        {
            ValidateBaseUri(baseUri);
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(entitySetName, "entitySetName");

            return(AppendSegment(baseUri, entitySetName, true /*escapeSegment*/));
        }
예제 #5
0
        /// <summary>
        /// Gets the association link URI for the specified navigation property.
        /// </summary>
        /// <param name="navigationPropertyName">The name of the navigation property to get the association link URI for.</param>
        /// <param name="associationLinkUrl">The value of the link URI as seen on the wire or provided explicitly by the user or previously returned by the metadata builder, which may be null.</param>
        /// <param name="hasAssociationLinkUrl">true if the value of the <paramref name="associationLinkUrl"/> was seen on the wire or provided explicitly by the user or previously returned by
        /// the metadata builder, false otherwise. This flag allows the metadata builder to determine whether a null association link url is an uninitialized value or a value that was set explicitly.</param>
        /// <returns>
        /// The association link URI for the navigation property.
        /// null if its not possible to determine the association link for the specified navigation property.
        /// </returns>
        internal override Uri GetAssociationLinkUri(string navigationPropertyName, Uri associationLinkUrl, bool hasAssociationLinkUrl)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(navigationPropertyName, "navigationPropertyName");

            return(hasAssociationLinkUrl ? associationLinkUrl : this.uriBuilder.BuildAssociationLinkUri(this.GetEditLink(), navigationPropertyName));
        }
예제 #6
0
        /// <summary>
        /// Create a EndPathToken given the Identifier and the NextToken (if any)
        /// </summary>
        /// <param name="identifier">The Identifier of the property to access.</param>
        /// <param name="nextToken">The NextToken token to access the property on. </param>
        public EndPathToken(string identifier, QueryToken nextToken)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(identifier, "identifier");

            this.identifier = identifier;
            this.nextToken  = nextToken;
        }
        /// <summary>
        /// Create a PropertyAccessQueryToken given the name and the parent (if any)
        /// </summary>
        /// <param name="name">The name of the property to access.</param>
        /// <param name="parent">The parent token to access the property on.  Pass no if this property has no parent.</param>
        public PropertyAccessQueryToken(string name, QueryToken parent)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(name, "name");

            this.name   = name;
            this.parent = parent;
        }
예제 #8
0
        /// <summary>
        /// Constructs a new instance of Astoria type using the specified clr type.
        /// </summary>
        /// <param name="instanceType">CLR type that represents the flow format inside the Astoria runtime.</param>
        /// <param name="resourceTypeKind">Kind of the resource type.</param>
        /// <param name="baseType">Base type of the resource type.</param>
        /// <param name="namespaceName">Namespace name of the given resource type.</param>
        /// <param name="name">Name of the given resource type.</param>
        /// <param name="isAbstract">Whether the resource type is an abstract type or not.</param>
        public ResourceType(
            Type instanceType,
            ResourceTypeKind resourceTypeKind,
            ResourceType baseType,
            string namespaceName,
            string name,
            bool isAbstract)
            : this(instanceType, baseType, namespaceName, name, isAbstract)
        {
            ExceptionUtils.CheckArgumentNotNull(instanceType, "instanceType");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(name, "name");
            CheckResourceTypeKind(resourceTypeKind, "resourceTypeKind");
            if (resourceTypeKind == ResourceTypeKind.Primitive || resourceTypeKind == ResourceTypeKind.MultiValue)
            {
                throw new ArgumentException(Strings.ResourceType_InvalidValueForResourceTypeKind, "resourceTypeKind");
            }

            if (baseType != null && baseType.ResourceTypeKind != resourceTypeKind)
            {
                throw new ArgumentException(
                          Strings.ResourceType_InvalidResourceTypeKindInheritance(resourceTypeKind.ToString(), baseType.ResourceTypeKind.ToString()),
                          "resourceTypeKind");
            }

            if (instanceType.IsValueType)
            {
                throw new ArgumentException(Strings.ResourceType_TypeCannotBeValueType, "instanceType");
            }

            this.resourceTypeKind = resourceTypeKind;
        }
예제 #9
0
        /// <summary>
        /// Initializes a new <see cref="ServiceOperation"/> instance.
        /// </summary>
        /// <param name="name">name of the service operation.</param>
        /// <param name="resultKind">Kind of result expected from this operation.</param>
        /// <param name="resultType">Type of element of the method result.</param>
        /// <param name="resultSet">EntitySet of the result expected from this operation.</param>
        /// <param name="method">Protocol (for example HTTP) method the service operation responds to.</param>
        /// <param name="parameters">In-order parameters for this operation.</param>
        public ServiceOperation(
            string name,
            ServiceOperationResultKind resultKind,
            ResourceType resultType,
            ResourceSet resultSet,
            string method,
            IEnumerable <ServiceOperationParameter> parameters)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(name, "name");
            CheckServiceOperationResultKind(resultKind, "resultKind");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(method, "method");

            if ((resultKind == ServiceOperationResultKind.Void && resultType != null) ||
                (resultKind != ServiceOperationResultKind.Void && resultType == null))
            {
                throw new ArgumentException(Strings.ServiceOperation_ResultTypeAndKindMustMatch("resultKind", "resultType", ServiceOperationResultKind.Void));
            }

            if ((resultType == null || resultType.ResourceTypeKind != ResourceTypeKind.EntityType) && resultSet != null)
            {
                throw new ArgumentException(Strings.ServiceOperation_ResultSetMustBeNull("resultSet", "resultType"));
            }

            if (resultType != null && resultType.ResourceTypeKind == ResourceTypeKind.EntityType && (resultSet == null || !resultSet.ResourceType.IsAssignableFrom(resultType)))
            {
                throw new ArgumentException(Strings.ServiceOperation_ResultTypeAndResultSetMustMatch("resultType", "resultSet"));
            }

            if (resultType != null && resultType.ResourceTypeKind == ResourceTypeKind.MultiValue)
            {
                throw new ArgumentException(Strings.ServiceOperation_InvalidResultType(resultType.FullName));
            }

            if (method != HttpConstants.HttpMethodGet && method != HttpConstants.HttpMethodPost)
            {
                throw new ArgumentException(Strings.ServiceOperation_NotSupportedProtocolMethod(method, name));
            }

            this.name        = name;
            this.resultKind  = resultKind;
            this.resultType  = resultType;
            this.resourceSet = resultSet;
            this.method      = method;
            if (parameters == null)
            {
                this.parameters = ServiceOperation.emptyParameterCollection;
            }
            else
            {
                this.parameters = new ReadOnlyCollection <ServiceOperationParameter>(new List <ServiceOperationParameter>(parameters));
                HashSet <string> paramNames = new HashSet <string>(StringComparer.Ordinal);
                foreach (ServiceOperationParameter p in this.parameters)
                {
                    if (!paramNames.Add(p.Name))
                    {
                        throw new ArgumentException(Strings.ServiceOperation_DuplicateParameterName(p.Name), "parameters");
                    }
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Resolves a name to an <see cref="IEdmEntitySet"/> instance.
        /// </summary>
        /// <param name="model">The model to resolve the name against.</param>
        /// <param name="entitySetName">The name of the entity set to look up.</param>
        /// <returns>An <see cref="IEdmEntitySet"/> instance with the specified <paramref name="entitySetName"/> or null if no such entity set exists.</returns>
        public static IEdmEntitySet TryResolveEntitySet(this IEdmModel model, string entitySetName)
        {
            ExceptionUtils.CheckArgumentNotNull(model, "model");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(entitySetName, "entitySetName");

            IEnumerable <IEdmEntityContainer> entityContainers = model.EntityContainers();

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

            IEdmEntitySet entitySet = null;

            foreach (IEdmEntityContainer container in entityContainers)
            {
                entitySet = container.FindEntitySet(entitySetName);
                if (entitySet != null)
                {
                    break;
                }
            }

            return(entitySet);
        }
예제 #11
0
        /// <summary>
        /// Resolves a name to an <see cref="IEdmFunctionImport"/> instance.
        /// </summary>
        /// <param name="model">The model to resolve the name against.</param>
        /// <param name="operationName">The name of the service operation to look up.</param>
        /// <returns>An <see cref="IEdmFunctionImport"/> instance with the specified <paramref name="operationName"/> or null if no such service operation exists.</returns>
        public static IEdmFunctionImport TryResolveServiceOperation(this IEdmModel model, string operationName)
        {
            ExceptionUtils.CheckArgumentNotNull(model, "model");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(operationName, "operationName");

            IEdmFunctionImport functionImport = null;

            foreach (IEdmFunctionImport import in model.ResolveFunctionImports(operationName))
            {
                if (model.IsServiceOperation(import))
                {
                    if (functionImport == null)
                    {
                        functionImport = import;
                    }
                    else
                    {
                        throw new ODataException(
                                  ODataErrorStrings.ODataQueryUtils_FoundMultipleServiceOperations(operationName));
                    }
                }
            }

            return(functionImport);
        }
예제 #12
0
        /// <summary>
        /// Get the operation title for the specified <paramref name="operationName"/>.
        /// </summary>
        /// <param name="operationName">The fully qualified name of the operation for which to get the target URI.</param>
        /// <returns>
        /// The title for the operation.
        /// null if it is not possible to determine the title for the specified operation.
        /// </returns>
        internal override string GetOperationTitle(string operationName)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(operationName, "operationName");

            // TODO: What is the convention for operation title?
            return(operationName);
        }
 /// <summary>
 /// Create a ConstantNode
 /// </summary>
 /// <param name="constantValue">This node's primitive value.</param>
 /// <param name="literalText">The literal text for this node's value, formatted according to the OData URI literal formatting rules.</param>
 /// <param name="typeReference">The typeReference of this node's value.</param>
 /// <exception cref="System.ArgumentNullException">Throws if the input literalText is null.</exception>
 public ConstantNode(object constantValue, string literalText, IEdmTypeReference typeReference)
     : this(constantValue)
 {
     ExceptionUtils.CheckArgumentStringNotNullOrEmpty(literalText, "literalText");
     this.LiteralText   = literalText;
     this.typeReference = typeReference;
 }
예제 #14
0
        /// <summary>
        /// Create a new FunctionCallQueryToken given name and arguments.
        /// </summary>
        /// <param name="name">The name of the function to call.</param>
        /// <param name="arguments">The arguments for the function.</param>
        public FunctionCallQueryToken(string name, IEnumerable <QueryToken> arguments)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(name, "name");

            this.name      = name;
            this.arguments = new ReadOnlyEnumerable <QueryToken>(arguments ?? QueryToken.EmptyTokens);
        }
        /// <summary>
        /// Constructs a <see cref="SingleValueOpenPropertyAccessNode"/>.
        /// </summary>
        /// <param name="source">The value containing this property.</param>
        /// <param name="openPropertyName">The name of the open property to be bound outside the EDM model.</param>
        /// <exception cref="System.ArgumentNullException">Throws if the input source or openPropertyName is null.</exception>
        public SingleValueOpenPropertyAccessNode(SingleValueNode source, string openPropertyName)
        {
            ExceptionUtils.CheckArgumentNotNull(source, "source");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(openPropertyName, "openPropertyName");

            this.name   = openPropertyName;
            this.source = source;
        }
예제 #16
0
        /// <summary>
        /// Create an ComputeExpressionToken.
        /// </summary>
        /// <param name="expression">The computation token.</param>
        /// <param name="alias">The alias for the computation.</param>
        public ComputeExpressionToken(QueryToken expression, string alias)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(alias, "alias");

            this.expression = expression;
            this.alias      = alias;
        }
예제 #17
0
        /// <summary>
        /// Create a new FunctionCallToken using the given function name and parameter tokens.
        /// </summary>
        /// <param name="name">The name of the function to call.</param>
        /// <param name="arguments">The arguments for the function.</param>
        /// <param name="source">The syntactically bound parent of this function</param>
        public FunctionCallToken(string name, IEnumerable <FunctionParameterToken> arguments, QueryToken source)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(name, "name");

            this.name      = name;
            this.arguments = new ReadOnlyEnumerableForUriParser <FunctionParameterToken>(arguments ?? FunctionParameterToken.EmptyParameterList);
            this.source    = source;
        }
예제 #18
0
        /// <summary>
        /// Builds the URI for an entity set.
        /// </summary>
        /// <param name="baseUri">The URI to append to.</param>
        /// <param name="entitySetName">The entity set name.</param>
        /// <returns>The entity set URI.</returns>
        internal virtual Uri BuildEntitySetUri(Uri baseUri, string entitySetName)
        {
#if ODATA_CLIENT
            Util.CheckArgumentNullAndEmpty(entitySetName, "entitySetName");
#else
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(entitySetName, "entitySetName");
#endif
            return(null);
        }
예제 #19
0
        /// <summary>
        /// Create a TypeSegmentQueryToken given the name and the parent (if any)
        /// </summary>
        /// <param name="space">The namespace of the type segment.</param>
        /// <param name="name">The name of the type segment.</param>
        /// <param name="parent">The parent segment.</param>
        public CastToken(string space, string name, QueryToken parent)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(name, "name");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(space, "ns");

            this.space  = space;
            this.name   = name;
            this.parent = parent;
        }
예제 #20
0
        /// <summary>
        /// Builds the operation target URI for the specified <paramref name="operationName"/>.
        /// </summary>
        /// <param name="baseUri">The URI to append to.</param>
        /// <param name="operationName">The fully qualified name of the operation for which to get the target URI.</param>
        /// <param name="bindingParameterTypeName">The binding parameter type name to include in the target, or null/empty if there is none.</param>
        /// <param name="parameterNames">The parameter names to include in the target, or null/empty if there is none.</param>
        /// <returns>The target URI for the operation.</returns>
        internal virtual Uri BuildOperationTargetUri(Uri baseUri, string operationName, string bindingParameterTypeName, string parameterNames)
        {
#if ODATA_CLIENT
            Util.CheckArgumentNullAndEmpty(operationName, "operationName");
#else
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(operationName, "operationName");
#endif
            return(null);
        }
예제 #21
0
        /// <summary>
        /// Builds a URI with the given type name appended as a new segment on the base URI.
        /// </summary>
        /// <param name="baseUri">The URI to append to.</param>
        /// <param name="typeName">The fully qualified type name to append.</param>
        /// <returns>The URI with the type segment appended.</returns>
        internal virtual Uri AppendTypeSegment(Uri baseUri, string typeName)
        {
#if ODATA_CLIENT
            Util.CheckArgumentNullAndEmpty(typeName, "typeName");
#else
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(typeName, "typeName");
#endif
            return(null);
        }
예제 #22
0
        /// <summary>
        /// Get the operation target URI for the specified <paramref name="operationName"/>.
        /// </summary>
        /// <param name="operationName">The fully qualified name of the operation for which to get the target URI.</param>
        /// <param name="bindingParameterTypeName">The binding parameter type name to include in the target, or null/empty if there is none.</param>
        /// <returns>
        /// The target URI for the operation.
        /// null if it is not possible to determine the target URI for the specified operation.
        /// </returns>
        internal virtual Uri GetOperationTargetUri(string operationName, string bindingParameterTypeName)
        {
#if ASTORIA_CLIENT
            Util.CheckArgumentNullAndEmpty(operationName, "operationName");
#else
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(operationName, "operationName");
#endif
            return(null);
        }
예제 #23
0
        /// <summary>
        /// Builds the association link for the navigation property.
        /// </summary>
        /// <param name="baseUri">The URI to append to.</param>
        /// <param name="navigationPropertyName">The name of the navigation property to get the association link URI for.</param>
        /// <returns>The association link URI for the navigation property.</returns>
        internal virtual Uri BuildAssociationLinkUri(Uri baseUri, string navigationPropertyName)
        {
#if ODATA_CLIENT
            Util.CheckArgumentNullAndEmpty(navigationPropertyName, "navigationPropertyName");
#else
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(navigationPropertyName, "navigationPropertyName");
#endif
            return(null);
        }
예제 #24
0
        /// <summary>
        /// Removes all the function overloads from the custom uri functions.
        /// </summary>
        /// <param name="functionName">The custom function name</param>
        /// <returns>'False' if custom function signature doesn't exist. 'True' if function has been removed successfully</returns>
        /// <exception cref="ArgumentNullException">Arguments are null, or function signature return type is null</exception>
        public static bool RemoveCustomUriFunction(string functionName)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(functionName, "customFunctionName");

            lock (Locker)
            {
                return(CustomFunctions.Remove(functionName));
            }
        }
예제 #25
0
        /// <summary>
        /// Gets the <see cref="EntityPropertyMappingAttribute"/> for the specified <paramref name="propertyName"/>
        /// from the <paramref name="epmParentSourcePathSegment"/>.
        /// </summary>
        /// <param name="epmParentSourcePathSegment">The EPM source path segment for the parent of the property being written.</param>
        /// <param name="propertyName">The name of the property to get the <see cref="EntityPropertyMappingAttribute"/> for.</param>
        /// <returns>The <see cref="EntityPropertyMappingAttribute"/> for the specified <paramref name="propertyName"/> or null if none exists.</returns>
        internal static EntityPropertyMappingAttribute GetEntityPropertyMapping(EpmSourcePathSegment epmParentSourcePathSegment, string propertyName)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(propertyName, "propertyName");

            EpmSourcePathSegment epmSourcePathSegment = GetPropertySourcePathSegment(epmParentSourcePathSegment, propertyName);

            return(GetEntityPropertyMapping(epmSourcePathSegment));
        }
예제 #26
0
        /// <summary>
        /// Gets the association link URI for the specified navigation property.
        /// </summary>
        /// <param name="navigationPropertyName">The name of the navigation property to get the association link URI for.</param>
        /// <param name="associationLinkUrl">The value of the link URI as seen on the wire or provided explicitly by the user or previously returned by the metadata builder, which may be null.</param>
        /// <param name="hasAssociationLinkUrl">true if the value of the <paramref name="associationLinkUrl"/> was seen on the wire or provided explicitly by the user or previously returned by
        /// the metadata builder, false otherwise. This flag allows the metadata builder to determine whether a null association link url is an uninitialized value or a value that was set explicitly.</param>
        /// <returns>
        /// The association link URI for the navigation property.
        /// null if its not possible to determine the association link for the specified navigation property.
        /// </returns>
        internal virtual Uri GetAssociationLinkUri(string navigationPropertyName, Uri associationLinkUrl, bool hasAssociationLinkUrl)
        {
#if ODATA_CLIENT
            Util.CheckArgumentNullAndEmpty(navigationPropertyName, "navigationPropertyName");
#else
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(navigationPropertyName, "navigationPropertyName");
#endif
            return(null);
        }
예제 #27
0
        /// <summary>
        /// Get the operation title for the specified <paramref name="operationName"/>.
        /// </summary>
        /// <param name="operationName">The fully qualified name of the operation for which to get the target URI.</param>
        /// <returns>
        /// The title for the operation.
        /// null if it is not possible to determine the title for the specified operation.
        /// </returns>
        internal virtual string GetOperationTitle(string operationName)
        {
#if ODATA_CLIENT
            Util.CheckArgumentNullAndEmpty(operationName, "operationName");
#else
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(operationName, "operationName");
#endif
            return(null);
        }
예제 #28
0
        /// <summary>
        /// Binds a an end path token into a PropertyAccessToken, OpenPropertyToken, or FunctionCallToken.
        /// </summary>
        /// <param name="endPathToken">The property access token to bind.</param>
        /// <returns>A Query node representing this endpath token, bound to metadata.</returns>
        internal QueryNode BindEndPath(EndPathToken endPathToken)
        {
            ExceptionUtils.CheckArgumentNotNull(endPathToken, "EndPathToken");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(endPathToken.Identifier, "EndPathToken.Identifier");

            // Set the parent (get the parent type, so you can check whether the Identifier inside EndPathToken really is legit offshoot of the parent type)
            QueryNode parent = this.DetermineParentNode(endPathToken);

            QueryNode boundFunction;

            SingleValueNode singleValueParent = parent as SingleValueNode;

            if (singleValueParent == null)
            {
                if (functionCallBinder.TryBindEndPathAsFunctionCall(endPathToken, parent, state, out boundFunction))
                {
                    return(boundFunction);
                }

                // Collection with any or all expression is already supported and handled separately.
                // Add support of collection with $count segment.
                CollectionNode colNode = parent as CollectionNode;
                if (colNode != null && endPathToken.Identifier.Equals(UriQueryConstants.CountSegment))
                {
                    // create a collection count node for collection node property.
                    return(new CountNode(colNode));
                }

                throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyAccessSourceNotSingleValue(endPathToken.Identifier));
            }


            // Now that we have the parent type, can find its corresponding EDM type
            IEdmStructuredTypeReference structuredParentType =
                singleValueParent.TypeReference == null ? null : singleValueParent.TypeReference.AsStructuredOrNull();

            IEdmProperty property =
                structuredParentType == null ? null : this.Resolver.ResolveProperty(structuredParentType.StructuredDefinition(), endPathToken.Identifier);

            if (property != null)
            {
                return(GeneratePropertyAccessQueryNode(singleValueParent as SingleResourceNode, property, state));
            }

            if (endPathToken.Identifier == ExpressionConstants.QueryOptionCount)
            {
                return(new CountVirtualPropertyNode());
            }

            if (functionCallBinder.TryBindEndPathAsFunctionCall(endPathToken, singleValueParent, state, out boundFunction))
            {
                return(boundFunction);
            }

            return(GeneratePropertyAccessQueryForOpenType(endPathToken, singleValueParent));
        }
        /// <summary>
        /// Builds the association link for the navigation property.
        /// </summary>
        /// <param name="baseUri">The URI to append to.</param>
        /// <param name="navigationPropertyName">The name of the navigation property to get the association link URI for.</param>
        /// <returns>The association link URI for the navigation property.</returns>
        internal override Uri BuildAssociationLinkUri(Uri baseUri, string navigationPropertyName)
        {
            ValidateBaseUri(baseUri);
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(navigationPropertyName, "navigationPropertyName");

            Uri baseUriWithLinksSegment = AppendSegment(baseUri, navigationPropertyName, true /*escapeSegment*/);

            // We don't want the $ref segment to be escaped, so append that first without escaping, then append the property name with escaping
            return(AppendSegment(baseUriWithLinksSegment, ODataConstants.EntityReferenceSegmentName, false /*escapeSegment*/));
        }
예제 #30
0
        /// <summary>
        /// Create a new FunctionCallToken using the given function name and argument values.
        /// </summary>
        /// <param name="name">The name of the function to call.</param>
        /// <param name="argumentValues">The argument values for the function.</param>
        public FunctionCallToken(string name, IEnumerable <QueryToken> argumentValues)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(name, "name");

            this.name      = name;
            this.arguments = argumentValues == null ?
                             new ReadOnlyEnumerableForUriParser <FunctionParameterToken>(FunctionParameterToken.EmptyParameterList) :
                             new ReadOnlyEnumerableForUriParser <FunctionParameterToken>(argumentValues.Select(v => new FunctionParameterToken(null, v)));
            this.source = null;
        }