public void NameIsSetCorrectly()
        {
            var entityCollectionFunctionCallNode = new EntityCollectionFunctionCallNode("stuff", new List <IEdmFunction>()
            {
                HardCodedTestModel.GetFunctionForHasJob()
            }, null, this.entityCollectionTypeReference, HardCodedTestModel.GetPeopleSet(), null);

            entityCollectionFunctionCallNode.Name.Should().Be("stuff");
        }
        public void KindIsSingleEntityFunction()
        {
            var entityFunctionCallNode = new EntityCollectionFunctionCallNode("stuff", new List <IEdmFunction>()
            {
                HardCodedTestModel.GetFunctionForHasJob()
            }, new QueryNode[] { new ConstantNode(1) }, this.entityCollectionTypeReference, HardCodedTestModel.GetPeopleSet(), null);

            entityFunctionCallNode.Kind.Should().Be(QueryNodeKind.EntityCollectionFunctionCall);
        }
 /// <summary>
 /// Translate an EntityCollectionFunctionCallNode.
 /// </summary>
 /// <param name="nodeIn">The node to be translated.</param>
 /// <returns>The translated node.</returns>
 public override QueryNode Visit(EntityCollectionFunctionCallNode nodeIn)
 {
     return(new EntityCollectionFunctionCallNode(
                nodeIn.Name,
                nodeIn.Functions,
                nodeIn.Parameters.Select(p => p.Accept(this)),
                nodeIn.CollectionType,
                (IEdmEntitySetBase)nodeIn.NavigationSource,
                nodeIn.Source == null ? null : nodeIn.Source.Accept(this)));
 }
        public void EntityTypeReferenceSetCorrectly()
        {
            var entityFunctionCallNode = new EntityCollectionFunctionCallNode("stuff", new List <IEdmFunction>()
            {
                HardCodedTestModel.GetFunctionForHasJob()
            }, new QueryNode[] { new ConstantNode(1) }, this.entityCollectionTypeReference, HardCodedTestModel.GetPeopleSet(), null);

            entityFunctionCallNode.ItemType.Should().BeSameAs(this.entityTypeReference);
            entityFunctionCallNode.EntityItemType.Should().BeSameAs(this.entityTypeReference);
        }
        public void ArgumentsSetCorrectly()
        {
            var entityFunctionCallNode = new EntityCollectionFunctionCallNode("stuff", new List <IEdmFunction>()
            {
                HardCodedTestModel.GetFunctionForHasJob()
            }, new QueryNode[] { new ConstantNode(1) }, this.entityCollectionTypeReference, HardCodedTestModel.GetPeopleSet(), null);

            entityFunctionCallNode.Parameters.Should().HaveCount(1);
            entityFunctionCallNode.Parameters.ElementAt(0).ShouldBeConstantQueryNode(1);
        }
        /// <summary>
        /// Translates a <see cref="EntityCollectionFunctionCallNode"/> into a corresponding <see cref="string"/>.
        /// </summary>
        /// <param name="node">The node to translate.</param>
        /// <returns>The translated string of EntityCollectionFunctionCallNode.</returns>
        public override string Visit(EntityCollectionFunctionCallNode node)
        {
            string result = node.Name;

            if (node.Source != null)
            {
                result = this.TranslatePropertyAccess(node.Source, result);
            }

            return(this.TranslateFunctionCall(result, node.Parameters));
        }
        /// <summary>
        /// Translates a <see cref="EntityCollectionFunctionCallNode"/> into a corresponding <see cref="String"/>.
        /// </summary>
        /// <param name="node">The node to translate.</param>
        /// <returns>The translated String of EntityCollectionFunctionCallNode.</returns>
        public override String Visit(EntityCollectionFunctionCallNode node)
        {
            ExceptionUtils.CheckArgumentNotNull(node, "node");
            String result = node.Name;

            if (node.Source != null)
            {
                result = this.TranslatePropertyAccess(node.Source, result);
            }

            return(this.TranslateFunctionCall(result, node.Parameters));
        }
Exemple #8
0
 /// <summary>
 /// Visit a EntityCollectionFunctionCallNode
 /// </summary>
 /// <param name="nodeIn">The node to visit</param>
 /// <returns>The translated expression</returns>
 public override Expression Visit(EntityCollectionFunctionCallNode nodeIn)
 {
     throw new NotImplementedException();
 }
 public void KindIsSingleEntityFunction()
 {
     var entityFunctionCallNode = new EntityCollectionFunctionCallNode("stuff", new List<IEdmFunction>() { HardCodedTestModel.GetFunctionForHasJob() }, new QueryNode[] { new ConstantNode(1) }, this.entityCollectionTypeReference, HardCodedTestModel.GetPeopleSet(), null);
     entityFunctionCallNode.Kind.Should().Be(QueryNodeKind.EntityCollectionFunctionCall);
 }
 public void EntityTypeReferenceSetCorrectly()
 {
     var entityFunctionCallNode = new EntityCollectionFunctionCallNode("stuff", new List<IEdmFunction>() { HardCodedTestModel.GetFunctionForHasJob() }, new QueryNode[] { new ConstantNode(1) }, this.entityCollectionTypeReference, HardCodedTestModel.GetPeopleSet(), null);
     entityFunctionCallNode.ItemType.Should().BeSameAs(this.entityTypeReference);
     entityFunctionCallNode.EntityItemType.Should().BeSameAs(this.entityTypeReference);
 }
 public void ArgumentsSetCorrectly()
 {
     var entityFunctionCallNode = new EntityCollectionFunctionCallNode("stuff", new List<IEdmFunction>() { HardCodedTestModel.GetFunctionForHasJob() }, new QueryNode[] { new ConstantNode(1) }, this.entityCollectionTypeReference, HardCodedTestModel.GetPeopleSet(), null);
     entityFunctionCallNode.Parameters.Should().HaveCount(1);
     entityFunctionCallNode.Parameters.ElementAt(0).ShouldBeConstantQueryNode(1);
 }
 public void NameIsSetCorrectly()
 {
     var entityCollectionFunctionCallNode = new EntityCollectionFunctionCallNode("stuff", new List<IEdmFunction>() { HardCodedTestModel.GetFunctionForHasJob() }, null, this.entityCollectionTypeReference, HardCodedTestModel.GetPeopleSet(), null);
     entityCollectionFunctionCallNode.Name.Should().Be("stuff");
 }
Exemple #13
0
 public override IEnumerable <string> Visit(EntityCollectionFunctionCallNode nodeIn)
 {
     return(nodeIn.Source.Accept(this));
 }
Exemple #14
0
        private bool TryBindIdentifier(string identifier, IEnumerable <FunctionParameterToken> arguments, QueryNode parent, BindingState state, out QueryNode boundFunction)
        {
            boundFunction = null;

            IEdmType bindingType       = null;
            var      singleValueParent = parent as SingleValueNode;

            if (singleValueParent != null)
            {
                if (singleValueParent.TypeReference != null)
                {
                    bindingType = singleValueParent.TypeReference.Definition;
                }
            }
            else
            {
                var collectionValueParent = parent as CollectionNode;
                if (collectionValueParent != null)
                {
                    bindingType = collectionValueParent.CollectionType.Definition;
                }
            }

            if (!UriEdmHelpers.IsBindingTypeValid(bindingType))
            {
                return(false);
            }

            // All functions should be fully qualified, if they aren't they they aren't functions.
            // When using extension, there may be function call with unqualified name. So loose the restriction here.
            if (identifier.IndexOf(".", StringComparison.Ordinal) == -1 && this.Resolver.GetType() == typeof(ODataUriResolver))
            {
                return(false);
            }

            IEdmOperation operation;
            List <FunctionParameterToken> syntacticArguments = arguments == null ? new List <FunctionParameterToken>() : arguments.ToList();

            if (!FunctionOverloadResolver.ResolveOperationFromList(identifier, syntacticArguments.Select(ar => ar.ParameterName).ToList(), bindingType, state.Model, out operation, this.Resolver))
            {
                // TODO: FunctionOverloadResolver.ResolveOperationFromList() looks up the function by parameter names, but it shouldn't ignore parameter types. (test case ParseFilter_AliasInFunction_PropertyAsValue_TypeMismatch should fail)
                return(false);
            }

            if (singleValueParent != null && singleValueParent.TypeReference == null)
            {
                // if the parent exists, but has no type information, then we're in open type land, and we
                // shouldn't go any farther.
                throw new ODataException(ODataErrorStrings.FunctionCallBinder_CallingFunctionOnOpenProperty(identifier));
            }

            if (operation.IsAction())
            {
                return(false);
            }

            IEdmFunction function = (IEdmFunction)operation;

            // TODO:  $filter $orderby parameter expression which contains complex or collection should NOT be supported in this way
            //     but should be parsed into token tree, and binded to node tree: parsedParameters.Select(p => this.bindMethod(p));
            ICollection <FunctionParameterToken> parsedParameters = HandleComplexOrCollectionParameterValueIfExists(state.Configuration.Model, function, syntacticArguments, state.Configuration.Resolver.EnableCaseInsensitive);

            IEnumerable <QueryNode> boundArguments = parsedParameters.Select(p => this.bindMethod(p));

            boundArguments = boundArguments.ToList(); // force enumerable to run : will immediately evaluate all this.bindMethod(p).
            IEdmTypeReference returnType = function.ReturnType;
            IEdmEntitySetBase returnSet  = null;
            var singleEntityNode         = parent as SingleEntityNode;

            if (singleEntityNode != null)
            {
                returnSet = function.GetTargetEntitySet(singleEntityNode.NavigationSource, state.Model);
            }

            string functionName = function.FullName();

            if (returnType.IsEntity())
            {
                boundFunction = new SingleEntityFunctionCallNode(functionName, new[] { function }, boundArguments, (IEdmEntityTypeReference)returnType.Definition.ToTypeReference(), returnSet, parent);
            }
            else if (returnType.IsEntityCollection())
            {
                IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType;
                boundFunction = new EntityCollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, returnSet, parent);
            }
            else if (returnType.IsCollection())
            {
                IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType;
                boundFunction = new CollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, parent);
            }
            else
            {
                boundFunction = new SingleValueFunctionCallNode(functionName, new[] { function }, boundArguments, returnType, parent);
            }

            return(true);
        }
        private bool TryBindIdentifier(string identifier, IEnumerable<FunctionParameterToken> arguments, QueryNode parent, BindingState state, out QueryNode boundFunction)
        {
            boundFunction = null;

            IEdmType bindingType = null;
            var singleValueParent = parent as SingleValueNode;
            if (singleValueParent != null)
            {
                if (singleValueParent.TypeReference != null)
                {
                    bindingType = singleValueParent.TypeReference.Definition;
                }
            }
            else
            {
                var collectionValueParent = parent as CollectionNode;
                if (collectionValueParent != null)
                {
                    bindingType = collectionValueParent.CollectionType.Definition;
                }
            }

            if (!UriEdmHelpers.IsBindingTypeValid(bindingType))
            {
                return false;
            }

            // All functions should be fully qualified, if they aren't they they aren't functions.
            // When using extension, there may be function call with unqualified name. So loose the restriction here.
            if (identifier.IndexOf(".", StringComparison.Ordinal) == -1 && this.Resolver.GetType() == typeof(ODataUriResolver))
            {
                return false;
            }

            IEdmOperation operation;
            List<FunctionParameterToken> syntacticArguments = arguments == null ? new List<FunctionParameterToken>() : arguments.ToList();
            if (!FunctionOverloadResolver.ResolveOperationFromList(identifier, syntacticArguments.Select(ar => ar.ParameterName).ToList(), bindingType, state.Model, out operation, this.Resolver))
            {
                // TODO: FunctionOverloadResolver.ResolveOperationFromList() looks up the function by parameter names, but it shouldn't ignore parameter types. (test case ParseFilter_AliasInFunction_PropertyAsValue_TypeMismatch should fail)
                return false;
            }

            if (singleValueParent != null && singleValueParent.TypeReference == null)
            {
                // if the parent exists, but has no type information, then we're in open type land, and we 
                // shouldn't go any farther.
                throw new ODataException(ODataErrorStrings.FunctionCallBinder_CallingFunctionOnOpenProperty(identifier));
            }

            if (operation.IsAction())
            {
                return false;
            }

            IEdmFunction function = (IEdmFunction)operation;

            // TODO:  $filter $orderby parameter expression which contains complex or collection should NOT be supported in this way
            //     but should be parsed into token tree, and binded to node tree: parsedParameters.Select(p => this.bindMethod(p));
            ICollection<FunctionParameterToken> parsedParameters = HandleComplexOrCollectionParameterValueIfExists(state.Configuration.Model, function, syntacticArguments, state.Configuration.Resolver.EnableCaseInsensitive);

            IEnumerable<QueryNode> boundArguments = parsedParameters.Select(p => this.bindMethod(p));
            boundArguments = boundArguments.ToList(); // force enumerable to run : will immediately evaluate all this.bindMethod(p).
            IEdmTypeReference returnType = function.ReturnType;
            IEdmEntitySetBase returnSet = null;
            var singleEntityNode = parent as SingleEntityNode;
            if (singleEntityNode != null)
            {
                returnSet = function.GetTargetEntitySet(singleEntityNode.NavigationSource, state.Model);
            }

            string functionName = function.FullName();

            if (returnType.IsEntity())
            {
                boundFunction = new SingleEntityFunctionCallNode(functionName, new[] { function }, boundArguments, (IEdmEntityTypeReference)returnType.Definition.ToTypeReference(), returnSet, parent);
            }
            else if (returnType.IsEntityCollection())
            {
                IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType;
                boundFunction = new EntityCollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, returnSet, parent);
            }
            else if (returnType.IsCollection())
            {
                IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType;
                boundFunction = new CollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, parent);
            }
            else
            {
                boundFunction = new SingleValueFunctionCallNode(functionName, new[] { function }, boundArguments, returnType, parent);
            }

            return true;
        }
 /// <summary>
 /// Visit a EntityCollectionFunctionCallNode
 /// </summary>
 /// <param name="nodeIn">the node to visit</param>
 /// <returns>Defined by the implementer</returns>
 public virtual T Visit(EntityCollectionFunctionCallNode nodeIn)
 {
     throw new NotImplementedException();
 }
Exemple #17
0
        private bool TryBindIdentifier(string identifier, IEnumerable <FunctionParameterToken> arguments, QueryNode parent, BindingState state, out QueryNode boundFunction)
        {
            boundFunction = null;

            IEdmType bindingType       = null;
            var      singleValueParent = parent as SingleValueNode;

            if (singleValueParent != null)
            {
                if (singleValueParent.TypeReference != null)
                {
                    bindingType = singleValueParent.TypeReference.Definition;
                }
            }
            else
            {
                var collectionValueParent = parent as CollectionNode;
                if (collectionValueParent != null)
                {
                    bindingType = collectionValueParent.CollectionType.Definition;
                }
            }

            if (!UriEdmHelpers.IsBindingTypeValid(bindingType))
            {
                return(false);
            }

            IEdmFunctionImport            functionImport;
            List <FunctionParameterToken> syntacticArguments = arguments == null ? new List <FunctionParameterToken>() : arguments.ToList();

            if (!FunctionOverloadResolver.ResolveFunctionsFromList(identifier, syntacticArguments.Select(ar => ar.ParameterName).ToList(), bindingType, state.Model, out functionImport))
            {
                return(false);
            }

            if (singleValueParent != null && singleValueParent.TypeReference == null)
            {
                // if the parent exists, but has no type information, then we're in open type land, and we
                // shouldn't go any farther.
                throw new ODataException(ODataErrorStrings.FunctionCallBinder_CallingFunctionOnOpenProperty(identifier));
            }

            if (functionImport.IsSideEffecting)
            {
                return(false);
            }

            ICollection <FunctionParameterToken> parsedParameters;

            if (!FunctionParameterParser.TryParseFunctionParameters(syntacticArguments, state.Configuration, functionImport, out parsedParameters))
            {
                return(false);
            }

            IEnumerable <QueryNode> boundArguments = parsedParameters.Select(p => this.bindMethod(p));

            IEdmTypeReference returnType = functionImport.ReturnType;
            IEdmEntitySet     returnSet  = null;
            var singleEntityNode         = parent as SingleEntityNode;

            if (singleEntityNode != null)
            {
                returnSet = functionImport.GetTargetEntitySet(singleEntityNode.EntitySet, state.Model);
            }

            if (returnType.IsEntity())
            {
                boundFunction = new SingleEntityFunctionCallNode(identifier, new[] { functionImport }, boundArguments, (IEdmEntityTypeReference)returnType.Definition.ToTypeReference(), returnSet, parent);
            }
            else if (returnType.IsEntityCollection())
            {
                IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType;
                boundFunction = new EntityCollectionFunctionCallNode(identifier, new[] { functionImport }, boundArguments, collectionTypeReference, returnSet, parent);
            }
            else if (returnType.IsCollection())
            {
                IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType;
                boundFunction = new CollectionFunctionCallNode(identifier, new[] { functionImport }, boundArguments, collectionTypeReference, parent);
            }
            else
            {
                boundFunction = new SingleValueFunctionCallNode(identifier, new[] { functionImport }, boundArguments, returnType, parent);
            }

            return(true);
        }