/// <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; }
/// <summary> /// Constructs the event filter for the subscription. /// </summary> /// <returns>The event filter.</returns> public EventFilter ConstructFilter(Session session) { EventFilter filter = new EventFilter(); // the select clauses specify the values returned with each event notification. filter.SelectClauses = SelectClauses; // the where clause restricts the events returned by the server. // it works a lot like the WHERE clause in a SQL statement and supports // arbitrary expession trees where the operands are literals or event fields. ContentFilter whereClause = new ContentFilter(); // the code below constructs a filter that looks like this: // (Severity >= X OR LastSeverity >= X) AND (SuppressedOrShelved == False) AND (OfType(A) OR OfType(B)) // add the severity. ContentFilterElement element1 = null; ContentFilterElement element2 = null; if (Severity > EventSeverity.Min) { // select the Severity property of the event. SimpleAttributeOperand operand1 = new SimpleAttributeOperand(); operand1.TypeDefinitionId = ObjectTypeIds.BaseEventType; operand1.BrowsePath.Add(BrowseNames.Severity); operand1.AttributeId = Attributes.Value; // specify the value to compare the Severity property with. LiteralOperand operand2 = new LiteralOperand(); operand2.Value = new Variant((ushort)Severity); // specify that the Severity property must be GreaterThanOrEqual the value specified. element1 = whereClause.Push(FilterOperator.GreaterThanOrEqual, operand1, operand2); } // add the suppressed or shelved. if (!IgnoreSuppressedOrShelved) { // select the SuppressedOrShelved property of the event. SimpleAttributeOperand operand1 = new SimpleAttributeOperand(); operand1.TypeDefinitionId = ObjectTypeIds.BaseEventType; operand1.BrowsePath.Add(BrowseNames.SuppressedOrShelved); operand1.AttributeId = Attributes.Value; // specify the value to compare the Severity property with. LiteralOperand operand2 = new LiteralOperand(); operand2.Value = new Variant(false); // specify that the Severity property must Equal the value specified. element2 = whereClause.Push(FilterOperator.Equals, operand1, operand2); // chain multiple elements together with an AND clause. if (element1 != null) { element1 = whereClause.Push(FilterOperator.And, element1, element2); } else { element1 = element2; } } // add the event types. if (EventTypes != null && EventTypes.Count > 0) { element2 = null; // save the last element. for (int ii = 0; ii < EventTypes.Count; ii++) { // for this example uses the 'OfType' operator to limit events to thoses with specified event type. LiteralOperand operand1 = new LiteralOperand(); operand1.Value = new Variant(EventTypes[ii]); ContentFilterElement element3 = whereClause.Push(FilterOperator.OfType, operand1); // need to chain multiple types together with an OR clause. if (element2 != null) { element2 = whereClause.Push(FilterOperator.Or, element2, element3); } else { element2 = element3; } } // need to link the set of event types with the previous filters. if (element1 != null) { whereClause.Push(FilterOperator.And, element1, element2); } } filter.WhereClause = whereClause; // return filter. return filter; }
/// <summary> /// Converts an ContentFilterElement to a displayable string. /// </summary> /// <param name="nodeTable">The node table.</param> /// <returns>ContentFilterElement as a displayable string.</returns> public virtual string ToString(INodeTable nodeTable) { List <FilterOperand> operands = GetOperands(); string operand1 = (operands.Count > 0)?operands[0].ToString(nodeTable):null; string operand2 = (operands.Count > 1)?operands[1].ToString(nodeTable):null; string operand3 = (operands.Count > 2)?operands[2].ToString(nodeTable):null; StringBuilder buffer = new StringBuilder(); switch (FilterOperator) { case FilterOperator.OfType: case FilterOperator.InView: case FilterOperator.IsNull: case FilterOperator.Not: { buffer.AppendFormat("{0} '{1}'", FilterOperator, operand1); break; } case FilterOperator.And: case FilterOperator.Equals: case FilterOperator.GreaterThan: case FilterOperator.GreaterThanOrEqual: case FilterOperator.LessThan: case FilterOperator.LessThanOrEqual: case FilterOperator.Like: case FilterOperator.Or: { buffer.AppendFormat("'{1}' {0} '{2}'", FilterOperator, operand1, operand2); break; } case FilterOperator.Between: { buffer.AppendFormat("'{1}' <= '{0}' <= '{2}'", operand1, operand2, operand3); break; } case FilterOperator.Cast: { buffer.AppendFormat("({1}){0}", operand1, operand2); break; } case FilterOperator.InList: { buffer.AppendFormat("'{0}' in {", operand1); for (int ii = 1; ii < operands.Count; ii++) { if (ii < operands.Count - 1) { buffer.Append(", "); } buffer.AppendFormat("'{0}'", operands[ii].ToString()); } buffer.Append("}"); break; } case FilterOperator.RelatedTo: { buffer.AppendFormat("'{0}' ", operand1); string referenceType = operand2; if (operands.Count > 1) { LiteralOperand literalOperand = operands[1] as LiteralOperand; if (literalOperand != null) { INode node = nodeTable.Find(literalOperand.Value.Value as NodeId); if (node != null) { referenceType = Utils.Format("{0}", node); } } } buffer.AppendFormat("{0} '{1}'", referenceType, operand2); if (operand3 != null) { buffer.AppendFormat("Hops='{0}'", operand3); } break; } } return(buffer.ToString()); }
/// <summary> /// Returns the subscription filter to use. /// </summary> public EventFilter GetFilter() { ContentFilter whereClause = new ContentFilter(); ContentFilterElement element1 = whereClause.Push(FilterOperator.OfType, EventTypeId); EventFilter filter = new EventFilter(); for (int ii = 0; ii < Fields.Count; ii++) { filter.SelectClauses.Add(Fields[ii].Operand); if (Fields[ii].FilterValue != Variant.Null) { LiteralOperand operand = new LiteralOperand(); operand.Value = Fields[ii].FilterValue; ContentFilterElement element2 = whereClause.Push(Fields[ii].FilterOperator, Fields[ii].Operand, operand); element1 = whereClause.Push(FilterOperator.And, element1, element2); } } filter.WhereClause = whereClause; return filter; }
/// <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); }