/// <summary> /// Returns the operands for the element. /// </summary> /// <returns>The list of operands for the element.</returns> public List <FilterOperand> GetOperands() { List <FilterOperand> operands = new List <FilterOperand>(FilterOperands.Count); foreach (ExtensionObject extension in FilterOperands) { if (ExtensionObject.IsNull(extension)) { continue; } FilterOperand operand = extension.Body as FilterOperand; if (operand == null) { continue; } operands.Add(operand); } return(operands); }
/// <summary> /// Returns the value for the element. /// </summary> private object GetValue(FilterContext context, FilterOperand operand, IFilterTarget target) { // return the contained value for literal operands. LiteralOperand literal = operand as LiteralOperand; if (literal != null) { return literal.Value.Value; } // must query the filter target for simple attribute operands. SimpleAttributeOperand simpleAttribute = operand as SimpleAttributeOperand; if (simpleAttribute != null) { return target.GetAttributeValue( context, simpleAttribute.TypeDefinitionId, simpleAttribute.BrowsePath, simpleAttribute.AttributeId, simpleAttribute.ParsedIndexRange); } // must query the filter target for attribute operands. AttributeOperand attribute = operand as AttributeOperand; if (attribute != null) { // AttributeOperands only supported in advanced filter targets. IAdvancedFilterTarget advancedTarget = target as IAdvancedFilterTarget; if (advancedTarget == null) { return false; } return advancedTarget.GetRelatedAttributeValue( context, attribute.NodeId, attribute.BrowsePath, attribute.AttributeId, attribute.ParsedIndexRange); } // recursively evaluate element operands. ElementOperand element = operand as ElementOperand; if (element != null) { return Evaluate(context, target, (int)element.Index); } // oops - Validate() was not called. throw new ServiceResultException(StatusCodes.BadUnexpectedError, "FilterOperand is not supported."); }
/// <summary> /// Returns the operands for the element. /// </summary> private FilterOperand[] GetOperands(ContentFilterElement element, int expectedCount) { FilterOperand[] operands = new FilterOperand[element.FilterOperands.Count]; int ii = 0; foreach (ExtensionObject extension in element.FilterOperands) { if (ExtensionObject.IsNull(extension)) { throw new ServiceResultException(StatusCodes.BadUnexpectedError, "FilterOperand is null."); } FilterOperand operand = extension.Body as FilterOperand; if (operand == null) { throw new ServiceResultException(StatusCodes.BadUnexpectedError, "FilterOperand is not supported."); } operands[ii++] = operand; } if (expectedCount > 0 && expectedCount != operands.Length) { throw new ServiceResultException(StatusCodes.BadUnexpectedError, "ContentFilterElement does not have the correct number of operands."); } return operands; }
/// <summary> /// Validates the content filter element. /// </summary> /// <param name="context">The context.</param> /// <param name="index">The index.</param> /// <returns>The results of the validation.</returns> public virtual ContentFilter.ElementResult Validate(FilterContext context, int index) { ContentFilter.ElementResult result = new ContentFilter.ElementResult(null); // check the number of operands. int operandCount = -1; switch (m_filterOperator) { case FilterOperator.Not: case FilterOperator.IsNull: case FilterOperator.InView: case FilterOperator.OfType: { operandCount = 1; break; } case FilterOperator.And: case FilterOperator.Or: case FilterOperator.Equals: case FilterOperator.GreaterThan: case FilterOperator.GreaterThanOrEqual: case FilterOperator.LessThan: case FilterOperator.LessThanOrEqual: case FilterOperator.Like: case FilterOperator.Cast: { operandCount = 2; break; } case FilterOperator.Between: { operandCount = 3; break; } case FilterOperator.RelatedTo: { operandCount = 4; break; } case FilterOperator.InList: { operandCount = -1; break; } default: { break; } } if (operandCount != -1) { if (operandCount != m_filterOperands.Count) { result.Status = ServiceResult.Create( StatusCodes.BadEventFilterInvalid, "ContentFilterElement does not have the correct number of operands (Operator={0} OperandCount={1}).", m_filterOperator, operandCount); return(result); } } else { if (m_filterOperands.Count < 2) { result.Status = ServiceResult.Create( StatusCodes.BadEventFilterInvalid, "ContentFilterElement does not have the correct number of operands (Operator={0} OperandCount={1}).", m_filterOperator, m_filterOperands.Count); return(result); } } // validate the operands. bool error = false; for (int ii = 0; ii < m_filterOperands.Count; ii++) { ServiceResult operandResult = null; ExtensionObject operand = m_filterOperands[ii]; // check for null. if (ExtensionObject.IsNull(operand)) { operandResult = ServiceResult.Create( StatusCodes.BadEventFilterInvalid, "The FilterOperand cannot be Null."); result.OperandResults.Add(operandResult); error = true; continue; } // check that the extension object contains a filter operand. FilterOperand filterOperand = operand.Body as FilterOperand; if (filterOperand == null) { operandResult = ServiceResult.Create( StatusCodes.BadEventFilterInvalid, "The FilterOperand is not a supported type ({0}).", filterOperand.GetType()); result.OperandResults.Add(operandResult); error = true; continue; } // validate the operand. filterOperand.Parent = this; operandResult = filterOperand.Validate(context, index); if (ServiceResult.IsBad(operandResult)) { result.OperandResults.Add(operandResult); error = true; continue; } result.OperandResults.Add(null); } // ensure the global error code. if (error) { result.Status = StatusCodes.BadContentFilterInvalid; } else { result.OperandResults.Clear(); } return(result); }
/// <summary> /// Pushes a new element onto the stack. /// </summary> /// <param name="op">The filter operator.</param> /// <param name="operands">The operands.</param> /// <returns></returns> public ContentFilterElement Push(FilterOperator op, params object[] operands) { // check if nothing more to do. if (operands == null || operands.Length == 0) { throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, "ContentFilterElement does not have an operands."); } // create the element and set the operator. ContentFilterElement element = new ContentFilterElement(); element.FilterOperator = op; for (int ii = 0; ii < operands.Length; ii++) { // check if a FilterOperand was provided. FilterOperand filterOperand = operands[ii] as FilterOperand; if (filterOperand != null) { element.FilterOperands.Add(new ExtensionObject(filterOperand)); continue; } // check for reference to another ContentFilterElement. ContentFilterElement existingElement = operands[ii] as ContentFilterElement; if (existingElement != null) { int index = FindElementIndex(existingElement); if (index == -1) { throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, "ContentFilterElement is not part of the ContentFilter."); } ElementOperand operand = new ElementOperand(); operand.Index = (uint)index; element.FilterOperands.Add(new ExtensionObject(operand)); continue; } // assume a literal operand. LiteralOperand literalOperand = new LiteralOperand(); literalOperand.Value = new Variant(operands[ii]); element.FilterOperands.Add(new ExtensionObject(literalOperand)); } // insert the new element at the begining of the list. m_elements.Insert(0, element); // re-number ElementOperands since all element were shifted up. for (int ii = 0; ii < m_elements.Count; ii++) { foreach (ExtensionObject extension in m_elements[ii].FilterOperands) { if (extension != null) { ElementOperand operand = extension.Body as ElementOperand; if (operand != null) { operand.Index++; } } } } // return new element. return(element); }