public void ArgumentsSetCorrectly() { SingleEntityFunctionCallNode singleEntityFunctionCall = new SingleEntityFunctionCallNode("stuff", new QueryNode[] { new ConstantNode(1) }, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), HardCodedTestModel.GetPeopleSet()); singleEntityFunctionCall.Parameters.Should().HaveCount(1); singleEntityFunctionCall.Parameters.ElementAt(0).ShouldBeConstantQueryNode(1); }
/// <summary> /// Compares SingleEntityFunctionCall nodes. /// </summary> /// <param name="left">Left side of comparison</param> /// <param name="right">Right side of comparison</param> /// <returns>True if equal, otherwise false</returns> private bool Compare(SingleEntityFunctionCallNode left, SingleEntityFunctionCallNode right) { if (left.Parameters.Count() != right.Parameters.Count()) { return(false); } if (left.NavigationSource != right.NavigationSource) { return(false); } if (left.EntityTypeReference != right.EntityTypeReference) { return(false); } if (left.Name != right.Name) { return(false); } if (left.TypeReference != right.TypeReference) { return(false); } for (int i = 0; i < left.Parameters.Count(); ++i) { if (!this.Compare(left.Parameters.ElementAt(i), right.Parameters.ElementAt(i))) { return(false); } } return(true); }
public void ParametersSetCorrectly() { SingleEntityFunctionCallNode singleEntityFunctionCall = new SingleEntityFunctionCallNode("stuff", null, null, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), null, null); singleEntityFunctionCall.Parameters.Should().NotBeNull(); singleEntityFunctionCall.Parameters.Should().BeEmpty(); }
public void EntityTypeReferenceSetCorrectly() { SingleEntityFunctionCallNode singleEntityFunctionCall = new SingleEntityFunctionCallNode("stuff", new QueryNode[] { new ConstantNode(1) }, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()); singleEntityFunctionCall.EntityTypeReference.FullName().Should().Be(HardCodedTestModel.GetPersonTypeReference().FullName()); singleEntityFunctionCall.TypeReference.FullName().Should().Be(HardCodedTestModel.GetPersonTypeReference().FullName()); }
/// <summary> /// Translate a SingleEntityFunctionCallNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(SingleEntityFunctionCallNode nodeIn) { return(new SingleEntityFunctionCallNode( nodeIn.Name, nodeIn.Functions, nodeIn.Parameters.Select(p => p.Accept(this)), nodeIn.EntityTypeReference, nodeIn.NavigationSource, nodeIn.Source == null ? null : nodeIn.Source.Accept(this))); }
/// <summary> /// Translate a SingleEntityFunctionCallNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(SingleEntityFunctionCallNode nodeIn) { return(new SingleEntityFunctionCallNode( nodeIn.Name, nodeIn.Functions, // TODO 1941: Parameters property of SingleEntityFunctionCallNode should never be null. nodeIn.Parameters == null ? null : nodeIn.Parameters.Select(p => p.Accept(this)), nodeIn.EntityTypeReference, nodeIn.NavigationSource, nodeIn.Source == null ? null : nodeIn.Source.Accept(this))); }
/// <summary> /// Translates a <see cref="SingleEntityFunctionCallNode"/> into a corresponding <see cref="string"/>. /// </summary> /// <param name="node">The node to translate.</param> /// <returns>The translated string.</returns> public override string Visit(SingleEntityFunctionCallNode 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="SingleEntityFunctionCallNode"/> into a corresponding <see cref="String"/>. /// </summary> /// <param name="node">The node to translate.</param> /// <returns>The translated String.</returns> public override String Visit(SingleEntityFunctionCallNode 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)); }
/// <summary> /// Writes single entity function call node to string. /// </summary> /// <param name="node">Node to write to string</param> /// <returns>String representation of node.</returns> private static string ToString(SingleEntityFunctionCallNode node) { if (node != null) { return(tabHelper.Prefix + "SingleEntityFunctionCallNode" + tabHelper.Indent(() => tabHelper.Prefix + "NavigationSource = " + node.NavigationSource.Name + tabHelper.Prefix + "Type Reference = " + node.TypeReference + tabHelper.Prefix + "Name = " + node.Name + tabHelper.Prefix + "Function = " + ToString(node.Functions) + ArgumentsToString(node.Parameters) )); } return(String.Empty); }
/// <summary> /// Override this method to validate single entity function calls, such as 'cast'. /// </summary> /// <param name="node">The node to validate.</param> /// <param name="settings">The settings to use while validating.</param> /// <remarks> /// This method is intended to be called from method overrides in subclasses. This method also supports unit /// testing scenarios and is not intended to be called from user code. Call the Validate method to validate a /// <see cref="FilterQueryOption" /> instance. /// </remarks> public virtual void ValidateSingleEntityFunctionCallNode(SingleEntityFunctionCallNode node, ODataValidationSettings settings) { if (node == null) { throw Error.ArgumentNull("node"); } if (settings == null) { throw Error.ArgumentNull("settings"); } ValidateFunction(node.Name, settings); foreach (QueryNode argumentNode in node.Parameters) { ValidateQueryNode(argumentNode, settings); } }
/// <summary> /// Compares SingleEntityFunctionCall nodes. /// </summary> /// <param name="left">Left side of comparison</param> /// <param name="right">Right side of comparison</param> /// <returns>True if equal, otherwise false</returns> private bool Compare(SingleEntityFunctionCallNode left, SingleEntityFunctionCallNode right) { if (left.Parameters.Count() != right.Parameters.Count()) return false; if (left.NavigationSource != right.NavigationSource) return false; if (left.EntityTypeReference != right.EntityTypeReference) return false; if (left.Name != right.Name) return false; if (left.TypeReference != right.TypeReference) return false; for (int i = 0; i < left.Parameters.Count(); ++i) { if (!this.Compare(left.Parameters.ElementAt(i), right.Parameters.ElementAt(i))) return false; } return true; }
/// <summary> /// Visit a SingleEntityFunctionCallNode /// </summary> /// <param name="nodeIn">the node to visit</param> /// <returns>Defined by the implementer</returns> public virtual T Visit(SingleEntityFunctionCallNode nodeIn) { DebugUtils.CheckNoExternalCallers(); throw new NotImplementedException(); }
/// <summary> /// Visit a SingleEntityFunctionCallNode /// </summary> /// <param name="nodeIn">the node to visit</param> /// <returns>Defined by the implementer</returns> public virtual T Visit(SingleEntityFunctionCallNode nodeIn) { throw new NotImplementedException(); }
public void FunctionImportsAreSetCorrectly() { SingleEntityFunctionCallNode singleEntityFunctionCall = new SingleEntityFunctionCallNode("HasDog", HardCodedTestModel.GetHasDogOverloads(), null, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), ModelBuildingHelpers.BuildValidEntitySet(), null); singleEntityFunctionCall.Functions.Should().ContainExactly(HardCodedTestModel.GetHasDogOverloads()); }
public override IEnumerable <string> Visit(SingleEntityFunctionCallNode nodeIn) { return(nodeIn.Source.Accept(this)); }
/// <summary> /// Writes single entity function call node to string. /// </summary> /// <param name="node">Node to write to string</param> /// <returns>String representation of node.</returns> private static string ToString(SingleEntityFunctionCallNode node) { if (node != null) { return tabHelper.Prefix + "SingleEntityFunctionCallNode" + tabHelper.Indent(() => tabHelper.Prefix + "NavigationSource = " + node.NavigationSource.Name + tabHelper.Prefix + "Type Reference = " + node.TypeReference + tabHelper.Prefix + "Name = " + node.Name + tabHelper.Prefix + "Function = " + ToString(node.Functions) + ArgumentsToString(node.Parameters) ); } return String.Empty; }
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; }
public void NameIsSetCorrectly() { SingleEntityFunctionCallNode singleEntityFunctionCall = new SingleEntityFunctionCallNode("stuff", new QueryNode[] { }, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), HardCodedTestModel.GetPeopleSet()); singleEntityFunctionCall.ShouldBeSingleEntityFunctionCallNode("stuff"); }
public void KindIsSingleEntityFunction() { SingleEntityFunctionCallNode singleEntityFunctionCall = new SingleEntityFunctionCallNode("stuff", new QueryNode[] { new ConstantNode(1) }, ModelBuildingHelpers.BuildValidEntityType().ToTypeReference().AsEntity(), HardCodedTestModel.GetPeopleSet()); singleEntityFunctionCall.Kind.Should().Be(QueryNodeKind.SingleEntityFunctionCall); }
/// <summary> /// Visit a SingleEntityFunctionCallNode /// </summary> /// <param name="nodeIn">The node to visit</param> /// <returns>The translated expression</returns> public override Expression Visit(SingleEntityFunctionCallNode nodeIn) { throw new NotImplementedException(); }