/// <summary> /// Initialises a new instance of the <see cref="OrderByProperty"/> class. /// </summary> /// <param name="rawValue">The raw value.</param> /// <param name="model">The model.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="rawValue"/> or <paramref name="model"/> are null.</exception> /// <exception cref="ODataException">Thrown if there is an error parsing the <paramref name="rawValue"/>.</exception> internal OrderByProperty(string rawValue, EdmComplexType model) { RawValue = rawValue ?? throw new ArgumentNullException(nameof(rawValue)); if (model is null) { throw new ArgumentNullException(nameof(model)); } if (rawValue.IndexOf(' ') == -1) { PropertyPath = PropertyPath.For(rawValue, model); } else { PropertyPath = PropertyPath.For(rawValue.SubstringBefore(' '), model); if (rawValue.EndsWith(" asc", StringComparison.Ordinal)) { Direction = OrderByDirection.Ascending; } else if (rawValue.EndsWith(" desc", StringComparison.Ordinal)) { Direction = OrderByDirection.Descending; } else { throw ODataException.BadRequest(ExceptionMessage.InvalidOrderByDirection(rawValue.SubstringAfter(' '), PropertyPath.Property.Name), "$orderby"); } } }
/// <summary> /// Initialises a new instance of the <see cref="SelectExpandQueryOption" /> class. /// </summary> /// <param name="rawValue">The raw request value.</param> /// <param name="model">The model.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="rawValue"/> is null.</exception> internal SelectExpandQueryOption(string rawValue, EdmComplexType model) : base(rawValue) { if (model is null) { throw new ArgumentNullException(nameof(model)); } var propertyPaths = new List <PropertyPath>(); foreach (string propertyPathName in rawValue.Slice(',', rawValue.IndexOf('=') + 1)) { if (propertyPathName == "*") { if (rawValue.StartsWith("$select", StringComparison.Ordinal)) { propertyPaths.AddRange(model.Properties.Where(p => !p.IsNavigable).Select(PropertyPath.For)); } else if (rawValue.StartsWith("$expand", StringComparison.Ordinal)) { propertyPaths.AddRange(model.Properties.Where(p => p.IsNavigable).Select(PropertyPath.For)); } } else { propertyPaths.Add(PropertyPath.For(propertyPathName, model)); } } PropertyPaths = propertyPaths; }
public WhenConstructed() { TestHelper.EnsureEDM(); EdmComplexType model = EntityDataModel.Current.EntitySets["Customers"].EdmType; _operand = new PropertyAccessNode(PropertyPath.For(model.GetProperty("CompanyName"))); _node = new UnaryOperatorNode(_operand, _unaryOperatorKind); }
public WhenConstructed() { TestHelper.EnsureEDM(); EdmComplexType model = EntityDataModel.Current.EntitySets["Customers"].EdmType; _propertyPath = PropertyPath.For(model.GetProperty("CompanyName")); _node = new PropertyAccessNode(_propertyPath); }
private QueryNode ParseFunctionCallNode() { BinaryOperatorNode binaryNode = null; FunctionCallNode node = null; var stack = new Stack <FunctionCallNode>(); while (_tokens.Count > 0) { Token token = _tokens.Dequeue(); switch (token.TokenType) { case TokenType.Base64Binary: case TokenType.Date: case TokenType.DateTimeOffset: case TokenType.Decimal: case TokenType.Double: case TokenType.Duration: case TokenType.EdmType: case TokenType.Enum: case TokenType.False: case TokenType.Guid: case TokenType.Integer: case TokenType.Null: case TokenType.Single: case TokenType.String: case TokenType.TimeOfDay: case TokenType.True: ConstantNode constantNode = ConstantNodeParser.ParseConstantNode(token); if (stack.Count > 0) { stack.Peek().AddParameter(constantNode); } else { if (binaryNode == null) { throw ODataException.BadRequest(ExceptionMessage.GenericUnableToParseFilter, "$filter"); } binaryNode.Right = constantNode; } break; case TokenType.BinaryOperator: binaryNode = new BinaryOperatorNode(node, token.Value.ToBinaryOperatorKind(), null); break; case TokenType.CloseParentheses: if (_groupingDepth == 0) { throw ODataException.BadRequest(ExceptionMessage.UnableToParseFilter($"the closing parenthesis not expected", token.Position), "$filter"); } _groupingDepth--; if (stack.Count > 0) { FunctionCallNode lastNode = stack.Pop(); if (stack.Count > 0) { stack.Peek().AddParameter(lastNode); } else { if (binaryNode != null) { binaryNode.Right = lastNode; } else { node = lastNode; } } } break; case TokenType.Comma: if (_tokens.Count > 0 && _tokens.Peek().TokenType == TokenType.CloseParentheses) { // If there is a comma in a function call, there should be another parameter followed by a closing comma throw ODataException.BadRequest(ExceptionMessage.UnableToParseFilter($"the function {node?.Name} has a missing parameter or extra comma", token.Position), "$filter"); } break; case TokenType.FunctionName: node = new FunctionCallNode(token.Value); break; case TokenType.OpenParentheses: if (_tokens.Count > 0 && _tokens.Peek().TokenType == TokenType.CloseParentheses) { // All OData functions have at least 1 or 2 parameters throw ODataException.BadRequest(ExceptionMessage.UnableToParseFilter($"the function {node?.Name} has no parameters specified", token.Position), "$filter"); } _groupingDepth++; stack.Push(node); break; case TokenType.PropertyName: var propertyAccessNode = new PropertyAccessNode(PropertyPath.For(token.Value, _model)); if (stack.Count > 0) { stack.Peek().AddParameter(propertyAccessNode); } else { if (binaryNode == null) { throw ODataException.BadRequest(ExceptionMessage.GenericUnableToParseFilter, "$filter"); } binaryNode.Right = propertyAccessNode; } break; default: throw ODataException.BadRequest(ExceptionMessage.UnableToParseFilter($"unexpected {token.Value}", token.Position), "$filter"); } } if (binaryNode != null) { return(binaryNode); } return(node); }
private QueryNode ParsePropertyAccessNode() { QueryNode result = null; QueryNode leftNode = null; BinaryOperatorKind operatorKind = BinaryOperatorKind.None; QueryNode rightNode = null; while (_tokens.Count > 0) { Token token = _tokens.Dequeue(); switch (token.TokenType) { case TokenType.Base64Binary: case TokenType.Date: case TokenType.DateTimeOffset: case TokenType.Decimal: case TokenType.Double: case TokenType.Duration: case TokenType.Enum: case TokenType.False: case TokenType.Guid: case TokenType.Integer: case TokenType.Null: case TokenType.Single: case TokenType.String: case TokenType.TimeOfDay: case TokenType.True: rightNode = ConstantNodeParser.ParseConstantNode(token); break; case TokenType.BinaryOperator: if (operatorKind != BinaryOperatorKind.None) { result = new BinaryOperatorNode(leftNode, operatorKind, rightNode); leftNode = null; rightNode = null; } operatorKind = token.Value.ToBinaryOperatorKind(); break; case TokenType.CloseParentheses: _groupingDepth--; break; case TokenType.FunctionName: rightNode = new FunctionCallNode(token.Value); break; case TokenType.OpenParentheses: _groupingDepth++; break; case TokenType.PropertyName: var propertyAccessNode = new PropertyAccessNode(PropertyPath.For(token.Value, _model)); if (leftNode is null) { leftNode = propertyAccessNode; } else if (rightNode is null) { rightNode = propertyAccessNode; } break; default: throw ODataException.BadRequest(ExceptionMessage.UnableToParseFilter($"unexpected {token.Value}", token.Position), "$filter"); } } result = result is null ? new BinaryOperatorNode(leftNode, operatorKind, rightNode) : new BinaryOperatorNode(result, operatorKind, leftNode ?? rightNode); return(result); }