/// <summary> /// Extracts the filter definition once a leaf is found. /// </summary> /// <param name="info">QueryInformation being filled.</param> /// <param name="binaryNode">BinaryOperatorNode the leaf belongs to.</param> /// <param name="constantNode">ConstantNode with the parameter definition.</param> private void ProcessLeafNode(QueryInformation info, BinaryOperatorNode binaryNode, ConstantNode constantNode) { try { // Necesary variables SingleValuePropertyAccessNode propertyAccessNode = binaryNode.Left as SingleValuePropertyAccessNode; SingleValueFunctionCallNode functioncall = binaryNode.Left as SingleValueFunctionCallNode; // The filter definition that is going to be added. FilterParameterDefinition filterdefinition = new FilterParameterDefinition(); // Populating common values. filterdefinition.FilteringOperator = (FilteringOperator)binaryNode.OperatorKind; filterdefinition.StringValue = constantNode.Value.ToString(); if (functioncall != null) { // it contains a function call propertyAccessNode = ParseFunctionCall(propertyAccessNode, functioncall, filterdefinition); } if (propertyAccessNode != null) { //it is a simple equals ParsePropertyAccessNode(info, propertyAccessNode, filterdefinition); } } catch (Exception ex) { LogException(ex); } }
/// <summary> /// Parses an ODataQueryOptions objects exposing its features in a custom object. /// </summary> /// <param name="options">ODataQueryOptions given by the ASP.NET Web Odata API controller.</param> /// <returns>A QueryInformation containing the parsing results.</returns> /// <remarks> /// We currently support only the Filter aspects of the ODataQueryOptions object. /// </remarks> public QueryInformation Parse(ODataQueryOptions options) { QueryInformation info = new QueryInformation(); ParseFilterData(options.Filter, info); return(info); }
/// <summary> /// Performs a Binary search on the abstract syntax tree of the filter expression. /// </summary> /// <param name="node">The node that needs to be searched on.</param> /// <param name="info">The QueryInformation where we are accumulating the filter definitions. </param> private void BinarySearchForNodes(QueryNode node, QueryInformation info) { try { var binaryNode = node as BinaryOperatorNode; if (binaryNode != null) { // We look for constant nodes that would mean a leaf have been reached. ConstantNode constantNode = GetConstantNode(binaryNode); if (constantNode != null) { ProcessLeafNode(info, binaryNode, constantNode); } else { BinarySearchForNodes(binaryNode.Left, info); BinarySearchForNodes(binaryNode.Right, info); } } else { var convertNode = node as ConvertNode; if (convertNode != null) { BinarySearchForNodes(convertNode.Source, info); } else { LogWarning(string.Format("Node wasn't casted as binary node. Type is {0}", node.GetType().FullName)); } } } catch (Exception ex) { LogException(ex); } }
/// <summary> /// Parses the Filter portion of the ODataQueryOptions object and adds its details to the used QueryInformation. /// </summary> /// <param name="filter">FilterQueryOption object contained in the ODataQueryOptions from the OData controller.</param> /// <param name="info">The QueryInformation object that is maintained to give back the results.</param> public void ParseFilterData(FilterQueryOption filter, QueryInformation info) { try { // If the filter comes null, there is no work to be done by this method. if (filter == null) { return; } // There is at least one parameter so we instantiate the collection in the info object. info.FilterParameters = new ODataFilterParameterCollection(); // The abstract syntax tree of the expression is a binary tree, we perform it here from the root. BinarySearchForNodes(filter.FilterClause.Expression, info); return; } catch (Exception ex) { LogException(ex); } }
/// <summary> /// Parses a Property access node. /// </summary> /// <param name="info">QueryInformation being filled.</param> /// <param name="propertyAccessNode">Property access node to be parsed.</param> /// <param name="filterdefinition">Filter definition being filled.</param> private static void ParsePropertyAccessNode(QueryInformation info, SingleValuePropertyAccessNode propertyAccessNode, FilterParameterDefinition filterdefinition) { filterdefinition.FieldName = propertyAccessNode.Property.Name; info.FilterParameters.Add(filterdefinition); }