Beispiel #1
0
        /// <summary>
        /// Validates the ContentFilter.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns>The result of validation.</returns>
        public Result Validate(FilterContext context)
        {
            Result result = new Result(null);

            // check for empty filter.
            if (m_elements == null || m_elements.Count == 0)
            {
                return(result);
            }

            bool error = false;

            for (int ii = 0; ii < m_elements.Count; ii++)
            {
                ContentFilterElement element = m_elements[ii];

                // check for null.
                if (element == null)
                {
                    ServiceResult nullResult = ServiceResult.Create(
                        StatusCodes.BadStructureMissing,
                        "ContentFilterElement is null (Index={0}).",
                        ii);

                    result.ElementResults.Add(new ElementResult(nullResult));
                    error = true;
                    continue;
                }

                element.Parent = this;

                // validate element.
                ElementResult elementResult = element.Validate(context, ii);

                if (ServiceResult.IsBad(elementResult.Status))
                {
                    result.ElementResults.Add(elementResult);
                    error = true;
                    continue;
                }

                result.ElementResults.Add(null);
            }

            // ensure the global error code.
            if (error)
            {
                result.Status = StatusCodes.BadContentFilterInvalid;
            }
            else
            {
                result.ElementResults.Clear();
            }

            return(result);
        }
Beispiel #2
0
        /// <summary>
        /// Finds the index of the specified element.
        /// </summary>
        /// <param name="target">The targetto be found.</param>
        /// <returns>The index of the specified element.</returns>
        private int FindElementIndex(ContentFilterElement target)
        {
            for (int ii = 0; ii < m_elements.Count; ii++)
            {
                if (Object.ReferenceEquals(target, m_elements[ii]))
                {
                    return(ii);
                }
            }

            return(-1);
        }
        /// <summary>
        /// Like FilterOperator
        /// </summary>
        private bool Like(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 2);

            object firstOperand = GetValue(context, operands[0], target);
            string lhs;
            LocalizedText firstOperandLocalizedText = firstOperand as LocalizedText;
            if (firstOperandLocalizedText != null)
            {
                lhs = firstOperandLocalizedText.Text;
            }
            else
            {
                lhs = firstOperand as string;
            }
            
            object secondOperand = GetValue(context, operands[1], target);
            string rhs;
            LocalizedText secondOperandLocalizedText = secondOperand as LocalizedText;
            if (secondOperandLocalizedText != null)
            {
                rhs = secondOperandLocalizedText.Text;
            }
            else
            {
                rhs = secondOperand as string;
            }

            // this operator requires strings.
            if (lhs == null || rhs == null)
            {
                return false;
            }
          
            return Match((string)lhs, (string)rhs);
        }
        /// <summary>
        /// InList FilterOperator
        /// </summary>
        private bool? InList(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 0);

            object value = GetValue(context, operands[0], target);

            // check for a match.
            for (int ii = 1; ii < operands.Length; ii++)
            {                
                object lhs = value;
                object rhs = GetValue(context, operands[ii], target);

                DoImplicitConversion(ref lhs, ref rhs);

                if (IsEqual(lhs, rhs))
                {
                    return true;
                }
            }

            // no match.
            return false;
        }
        /// <summary>
        /// Between FilterOperator
        /// </summary>
        private bool? Between(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 3);

            object value = GetValue(context, operands[0], target);

            object min = GetValue(context, operands[1], target);
            object max = GetValue(context, operands[2], target);
            
            // the min and max could be different data types so the implicit conversion must be done twice.
            object lhs = value;
            DoImplicitConversion(ref lhs, ref min);

            bool? result = null;
            
            if (lhs is IComparable && min is IComparable)
            {
                // check if never in range no matter what happens with the upper bound.
                if (((IComparable)lhs).CompareTo(min) < 0)
                {
                    return false;
                }

                result = true;
            }
            
            lhs = value;
            DoImplicitConversion(ref lhs, ref max);
            
            if (lhs is IComparable && max is IComparable)
            {
                // check if never in range no matter what happens with the lower bound.
                if (((IComparable)lhs).CompareTo(max) > 0)
                {
                    return false;
                }

                // can't determine if in range if lower bound could not be resolved.
                return result != null;
            }
            
            // return null if the types are not comparable.
            return null;
        }
        /// <summary>
        /// LessThanOrEqual FilterOperator
        /// </summary>
        private bool? LessThanOrEqual(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 2);

            object lhs = GetValue(context, operands[0], target);
            object rhs = GetValue(context, operands[1], target);

            DoImplicitConversion(ref lhs, ref rhs);

            if (lhs is IComparable && rhs is IComparable)
            {
                return ((IComparable)lhs).CompareTo(rhs) <= 0;
            }

            // return null if the types are not comparable.
            return null;
        }
        /// <summary>
        /// Like FilterOperator
        /// </summary>
        private bool Like(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 2);

            object lhs = GetValue(context, operands[0], target) as string;
            object rhs = GetValue(context, operands[1], target) as string;

            // this operator requires strings.
            if (lhs == null || rhs == null)
            {
                return false;
            }
          
            return Match((string)lhs, (string)rhs);
        }
 /// <summary>
 /// RelatedTo FilterOperator
 /// </summary>
 private bool RelatedTo(FilterContext context, IFilterTarget target, ContentFilterElement element)
 {
     return RelatedTo(context, target, element, null);
 }
        /// <summary>
        /// OfType FilterOperator
        /// </summary>
        private bool OfType(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 1);
            
            // get the desired type.
            NodeId typeDefinitionId = GetValue(context, operands[0], target) as NodeId;

            if (typeDefinitionId == null || target == null)
            {
                return false;
            }

            // check the type.
            try
            {
                return target.IsTypeOf(context, typeDefinitionId);
            }
            catch
            {
                return false;
            }
        }
        /// <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;
        }
Beispiel #11
0
        /// <summary>
        /// Finds the index of the specified element.
        /// </summary>
        /// <param name="target">The targetto be found.</param>
        /// <returns>The index of the specified element.</returns>
        private int FindElementIndex(ContentFilterElement target)
        {
            for (int ii = 0; ii < m_elements.Count; ii++)
            {
                if (Object.ReferenceEquals(target, m_elements[ii]))
                {
                    return ii;
                }
            }

            return -1;
        }
Beispiel #12
0
        /// <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;
        }
Beispiel #13
0
        /// <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>
        /// IsNull FilterOperator
        /// </summary>
        private bool IsNull(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 1);

            object rhs = GetValue(context, operands[0], target);
            
            if (rhs == null)
            {
                return true;
            }
            
            return false;
        }
        /// <summary>
        /// Or FilterOperator
        /// </summary>
        private bool? Or(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 2);

            bool? lhs = GetValue(context, operands[0], target) as bool?;

            // no need for further processing if first operand is true.
            if (lhs != null && lhs.Value)
            {
                return true;
            }

            bool? rhs = GetValue(context, operands[1], target) as bool?;
            
            if (lhs == null)
            {
                if (rhs == null || rhs == false)
            {
                return null;
            }
                else
                {
                    return true;
                }
            }

            if (rhs == null)
            {
                if (lhs == null || lhs == false)
                {
                    return null;
                }
                else
                {
                    return true;
                }
            }
            
            return lhs.Value || rhs.Value;
        }
        /// <summary>
        /// Cast FilterOperator
        /// </summary>
        private object Cast(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 2);
            
            // get the value to cast.
            object value = GetValue(context, operands[0], target);

            if (value == null)
            {
                return null;
            }

            // get the datatype to cast to.
            NodeId datatype = GetValue(context, operands[1], target) as NodeId;

            if (datatype == null)
            {
                return null;
            }

            BuiltInType targetType = GetBuiltInType(datatype);
            
            // cast the value.
            return Cast(value, targetType);
        }
        /// <summary>
        /// Not FilterOperator
        /// </summary>
        private bool? Not(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 1);

            bool? rhs = GetValue(context, operands[0], target) as bool?;
            
            if (rhs == null)
            {
                return null;
            }
            
            return !rhs.Value;
        }
        /// <summary>
        /// InView FilterOperator
        /// </summary>
        private bool InView(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            // views only supported in advanced filter targets.
            IAdvancedFilterTarget advancedFilter = target as IAdvancedFilterTarget;

            if (advancedFilter == null)
            {
                return false;
            }

            FilterOperand[] operands = GetOperands(element, 1);
            
            // get the desired type.
            NodeId viewId = GetValue(context, operands[0], target) as NodeId;

            if (viewId == null || target == null)
            {
                return false;
            }

            // check the target.
            try
            {
                return advancedFilter.IsInView(context, viewId);
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// Equals FilterOperator
        /// </summary>
        private bool Equals(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 2);

            object lhs = GetValue(context, operands[0], target);
            object rhs = GetValue(context, operands[1], target);

            DoImplicitConversion(ref lhs, ref rhs);

            return IsEqual(lhs, rhs);
        }
        /// <summary>
        /// RelatedTo FilterOperator
        /// </summary>
        private bool RelatedTo(FilterContext context, IFilterTarget target, ContentFilterElement element, NodeId intermediateNodeId)
        {
            // RelatedTo only supported in advanced filter targets.
            IAdvancedFilterTarget advancedTarget = target as IAdvancedFilterTarget;

            if (advancedTarget == null)
            {
                return false;
            }

            FilterOperand[] operands = GetOperands(element, 6);
            
            // get the type of the source.
            NodeId sourceTypeId = GetValue(context, operands[0], target) as NodeId;

            if (sourceTypeId == null)
            {
                return false;
            }
                        
            // get the type of reference to follow.
            NodeId referenceTypeId = GetValue(context, operands[2], target) as NodeId;

            if (referenceTypeId == null)
            {
                return false;
            }
            
            // get the number of hops
            int? hops = 1;

            object hopsValue = GetValue(context, operands[3], target);

            if (hopsValue != null)
            {
                hops = Cast(hopsValue, BuiltInType.Int32) as int?;

                if (hops == null)
                {
                    hops = 1;
                }
            }

            // get whether to include type definition subtypes.
            bool? includeTypeDefinitionSubtypes = true;

            object includeValue = GetValue(context, operands[4], target);

            if (includeValue != null)
            {
                includeTypeDefinitionSubtypes = Cast(includeValue, BuiltInType.Boolean) as bool?;

                if (includeTypeDefinitionSubtypes == null)
                {
                    includeTypeDefinitionSubtypes = true;
                }
            }

            // get whether to include reference type subtypes.
            bool? includeReferenceTypeSubtypes = true;

            includeValue = GetValue(context, operands[5], target);

            if (includeValue != null)
            {
                includeReferenceTypeSubtypes = Cast(includeValue, BuiltInType.Boolean) as bool?;

                if (includeReferenceTypeSubtypes == null)
                {
                    includeReferenceTypeSubtypes = true;
                }
            }

            NodeId targetTypeId = null;

            // check if elements are chained.
            ElementOperand chainedOperand = operands[1] as ElementOperand;

            if (chainedOperand != null)
            {
                if (chainedOperand.Index < 0 || chainedOperand.Index >= Elements.Count)
                {
                    return false;
                }

                ContentFilterElement chainedElement = Elements[(int)chainedOperand.Index];

                // get the target type from the first operand of the chained element.
                if (chainedElement.FilterOperator == FilterOperator.RelatedTo)
                {
                    FilterOperand nestedType = ExtensionObject.ToEncodeable(chainedElement.FilterOperands[0]) as FilterOperand;

                    targetTypeId = GetValue(context, nestedType, target) as NodeId;

                    if (targetTypeId == null)
                    {
                        return false;
                    }

                    // find the nodes that meet the criteria in the first link of the chain.
                    IList<NodeId> nodeIds = advancedTarget.GetRelatedNodes(
                        context,
                        intermediateNodeId,
                        sourceTypeId,
                        targetTypeId,
                        referenceTypeId,
                        hops.Value,
                        includeTypeDefinitionSubtypes.Value,
                        includeReferenceTypeSubtypes.Value);

                    if (nodeIds == null || nodeIds.Count == 0)
                    {
                        return false;
                    }
                    
                    // recursively follow the chain.
                    for (int ii = 0; ii < nodeIds.Count; ii++)
                    {
                        // one match is all that is required.
                        if (RelatedTo(context, target, chainedElement, nodeIds[ii]))
                        {
                            return true;
                        }
                    }

                    // no matches.
                    return false;
                }
            }
            
            // get the type of the target.
            if (targetTypeId == null)
            {
                targetTypeId = GetValue(context, operands[1], target) as NodeId;

                if (targetTypeId == null)
                {
                    return false;
                }
            }

            // check the target.            
            try
            {
                bool relatedTo = advancedTarget.IsRelatedTo(
                    context,
                    intermediateNodeId,
                    sourceTypeId,
                    targetTypeId,
                    referenceTypeId,
                    hops.Value,
                    includeTypeDefinitionSubtypes.Value,
                    includeReferenceTypeSubtypes.Value);

                return relatedTo;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// And FilterOperator
        /// </summary>
        private bool? And(FilterContext context, IFilterTarget target, ContentFilterElement element)
        {
            FilterOperand[] operands = GetOperands(element, 2);

            bool? lhs = GetValue(context, operands[0], target) as bool?;

            // no need for further processing if first operand is false.
            if (lhs != null && !lhs.Value)
            {
                return false;
            }

            bool? rhs = GetValue(context, operands[1], target) as bool?;
            
            if (lhs == null)
            {
                return (rhs == null)?null:(bool?)false;
            }
            
            if (rhs == null)
            {
                return (lhs == null)?null:(bool?)false;
            }

            return lhs.Value && rhs.Value;
        }