public Object GetFilterValue(MatchedEventMap matchedEvents, ExprEvaluatorContext evaluatorContext)
        {
            EventBean[] events = (EventBean[])matchedEvents.GetMatchingEventAsObjectByTag(_resultEventAsName);

            Object value = null;
            if (events == null)
            {
                Log.Warn("Matching events for tag '" + _resultEventAsName + "' returned a null result, using null value in filter criteria, for statement '" + _statementName + "'");
            }
            else if (_resultEventIndex > (events.Length - 1))
            {
                Log.Warn("Matching events for tag '" + _resultEventAsName + "' returned no result for index " + _resultEventIndex + " at array length " + events.Length + ", using null value in filter criteria, for statement '" + _statementName + "'");
            }
            else
            {
                value = events[_resultEventIndex].Get(_resultEventProperty);
            }

            // Coerce if necessary
            if (_isMustCoerce)
            {
                value = CoercerFactory.CoerceBoxed(value, _coercionType);
            }
            return value;
        }
Exemplo n.º 2
0
        public object Evaluate(EvaluateParams evaluateParams)
        {
            if (InstrumentationHelper.ENABLED)
            {
                InstrumentationHelper.Get().QExprCoalesce(this);
            }
            Object value;

            // Look for the first non-null return value
            for (var i = 0; i < _evaluators.Length; i++)
            {
                value = _evaluators[i].Evaluate(evaluateParams);

                if (value != null)
                {
                    // Check if we need to coerce
                    if (_isNumericCoercion[i])
                    {
                        value = CoercerFactory.CoerceBoxed(value, _resultType);
                    }
                    if (InstrumentationHelper.ENABLED)
                    {
                        InstrumentationHelper.Get().AExprCoalesce(value);
                    }
                    return(value);
                }
            }

            if (InstrumentationHelper.ENABLED)
            {
                InstrumentationHelper.Get().AExprCoalesce(null);
            }
            return(null);
        }
Exemplo n.º 3
0
        public static MultiKeyUntyped GetMultiKey(EventBean[] eventPerStream,
                                                  EventPropertyGetter[] propertyGetters,
                                                  int[] keyStreamNums,
                                                  Type[] coercionTypes)
        {
            Object[] keyValues = GetPropertyArray(eventPerStream, propertyGetters, keyStreamNums);
            if (coercionTypes == null)
            {
                return(new MultiKeyUntyped(keyValues));
            }

            for (int ii = 0; ii < coercionTypes.Length; ii++)
            {
                var key = keyValues[ii];
                if ((key != null) && (key.GetType() != coercionTypes[ii]))
                {
                    if (key.IsNumber())
                    {
                        key           = CoercerFactory.CoerceBoxed(key, coercionTypes[ii]);
                        keyValues[ii] = key;
                    }
                }
            }

            return(new MultiKeyUntyped(keyValues));
        }
Exemplo n.º 4
0
        public void CheckAndWrite(String variableName, int agentInstanceId, Object newValue)
        {
            var metaData       = _variables.Get(variableName);
            var variableNumber = metaData.VariableNumber;

            if (newValue == null)
            {
                Write(variableNumber, agentInstanceId, null);
                return;
            }

            var valueType = newValue.GetType();

            if (metaData.EventType != null)
            {
                if ((!TypeHelper.IsSubclassOrImplementsInterface(newValue.GetType(), metaData.EventType.UnderlyingType)))
                {
                    throw new VariableValueException("Variable '" + variableName
                                                     + "' of declared event type '" + metaData.EventType.Name + "' underlying type '" + metaData.EventType.UnderlyingType.FullName +
                                                     "' cannot be assigned a value of type '" + valueType.FullName + "'");
                }
                var eventBean = _eventAdapterService.AdapterForType(newValue, metaData.EventType);
                Write(variableNumber, agentInstanceId, eventBean);
                return;
            }

            var variableType = metaData.VariableType;

            if ((valueType == variableType) || (variableType == typeof(object)))
            {
                Write(variableNumber, agentInstanceId, newValue);
                return;
            }

            // Look for simple boxing rules
            var valueTypeBoxed    = valueType.GetBoxedType();
            var variableTypeBoxed = variableType.GetBoxedType();

            if (((valueType != valueTypeBoxed) || (variableType != variableTypeBoxed)) && ((valueTypeBoxed == variableTypeBoxed)))
            {
                Write(variableNumber, agentInstanceId, newValue);
                return;
            }

            if ((!variableType.IsNumeric()) || (!valueType.IsNumeric()))
            {
                throw new VariableValueException(VariableServiceUtil.GetAssigmentExMessage(variableName, variableType, valueType));
            }

            // determine if the expression type can be assigned
            if (!(TypeHelper.CanCoerce(valueType, variableType)))
            {
                throw new VariableValueException(VariableServiceUtil.GetAssigmentExMessage(variableName, variableType, valueType));
            }

            object valueCoerced = CoercerFactory.CoerceBoxed(newValue, variableType);

            Write(variableNumber, agentInstanceId, valueCoerced);
        }
 protected override Object Coerce(Object value)
 {
     if (value != null && value.GetType() != _coercionType)
     {
         if (value.IsNumber())
         {
             return(CoercerFactory.CoerceBoxed(value, _coercionType));
         }
     }
     return(value);
 }
Exemplo n.º 6
0
 /// <summary>
 /// The MayCoerceNonNull
 /// </summary>
 /// <param name="value">The <see cref="Object"/></param>
 /// <param name="coercionType">The <see cref="Type"/></param>
 /// <returns>The <see cref="Object"/></returns>
 private static Object MayCoerceNonNull(Object value, Type coercionType)
 {
     if (value.GetType() == coercionType)
     {
         return(value);
     }
     if (TypeHelper.IsNumber(value))
     {
         return(CoercerFactory.CoerceBoxed(value, coercionType));
     }
     return(value);
 }
Exemplo n.º 7
0
        public static Object Coerce(Object target, Type coercionType)
        {
            if (coercionType == null)
            {
                return(target);
            }

            if ((target != null) && (target.GetType().GetBoxedType() != coercionType))
            {
                if (target.IsNumber())
                {
                    return(CoercerFactory.CoerceBoxed(target, coercionType));
                }
            }
            return(target);
        }
Exemplo n.º 8
0
        /// <summary>Returns the set of events that have the same property value as the given event. </summary>
        /// <param name="keys">to compare against</param>
        /// <returns>set of events with property value, or null if none found (never returns zero-sized set)</returns>
        public override ISet <EventBean> Lookup(Object[] keys)
        {
            for (int i = 0; i < keys.Length; i++)
            {
                var coercionType = CoercionTypes[i];
                var key          = keys[i];

                if ((key != null) && (key.GetType() != coercionType))
                {
                    if (key.IsNumber())
                    {
                        key     = CoercerFactory.CoerceBoxed(key, CoercionTypes[i]);
                        keys[i] = key;
                    }
                }
            }

            return(PropertyIndex.Get(new MultiKeyUntyped(keys)));
        }
Exemplo n.º 9
0
        protected override Object[] GetKeys(EventBean[] eventsPerStream, ExprEvaluatorContext context)
        {
            var keys = base.GetKeys(eventsPerStream, context);

            for (var i = 0; i < keys.Length; i++)
            {
                var value = keys[i];

                var coercionType = _coercionTypes[i];
                if ((value != null) && (value.GetType() != coercionType))
                {
                    if (value.IsNumber())
                    {
                        value = CoercerFactory.CoerceBoxed(value, _coercionTypes[i]);
                    }
                    keys[i] = value;
                }
            }
            return(keys);
        }
Exemplo n.º 10
0
        public object Evaluate(EvaluateParams evaluateParams)
        {
            var result = new Mutable <object>();

            using (Instrument.With(
                       i => i.QExprMinMaxRow(this),
                       i => i.AExprMinMaxRow(result.Value)))
            {
                result.Value = _computer.Invoke(
                    evaluateParams.EventsPerStream,
                    evaluateParams.IsNewData,
                    evaluateParams.ExprEvaluatorContext);
                if (result.Value != null)
                {
                    result.Value = CoercerFactory.CoerceBoxed(result.Value, _resultType);
                }

                return(result.Value);
            }
        }
Exemplo n.º 11
0
        public Object GetFilterValue(MatchedEventMap matchedEvents, ExprEvaluatorContext evaluatorContext)
        {
            EventBean theEvent = matchedEvents.GetMatchingEventByTag(_resultEventAsName);
            if (theEvent == null)
            {
                throw new IllegalStateException("Matching event named " +
                        '\'' + _resultEventAsName + "' not found in event result set");
            }

            Object value = theEvent.Get(_resultEventProperty);

            // Coerce if necessary
            if (_isMustCoerce)
            {
                if (value != null)
                {
                    value = CoercerFactory.CoerceBoxed(value, _coercionType);
                }
            }
            return value;
        }
Exemplo n.º 12
0
        // expressions automatically coerce to the most upwards type
        // filters require the same type
        private static object HandleConstantsCoercion(FilterSpecLookupable lookupable, object constant)

        {
            var identNodeType = lookupable.ReturnType;
            if (!identNodeType.IsNumeric())
            {
                return constant; // no coercion required, other type checking performed by expression this comes from
            }

            if (constant == null) // null constant type
            {
                return null;
            }

            if (!constant.GetType().CanCoerce(identNodeType))
            {
                ThrowConversionError(constant.GetType(), identNodeType, lookupable.Expression);
            }

            var identNodeTypeBoxed = identNodeType.GetBoxedType();
            return CoercerFactory.CoerceBoxed(constant, identNodeTypeBoxed);
        }
Exemplo n.º 13
0
        private Object EvaluateCaseSyntax2(EventBean[] eventsPerStream, bool isNewData, ExprEvaluatorContext exprEvaluatorContext)
        {
            var evaluateParams = new EvaluateParams(eventsPerStream, isNewData, exprEvaluatorContext);

            // Case 2 expression example:
            //      case p when p1 then x [when p2 then y...] [else z]

            Object checkResult = _optionalCompareExprNode.Evaluate(evaluateParams);
            Object caseResult  = null;
            bool   matched     = false;

            foreach (UniformPair <ExprEvaluator> p in _whenThenNodeList)
            {
                var whenResult = p.First.Evaluate(evaluateParams);
                if (Compare(checkResult, whenResult))
                {
                    caseResult = p.Second.Evaluate(evaluateParams);
                    matched    = true;
                    break;
                }
            }

            if ((!matched) && (_optionalElseExprNode != null))
            {
                caseResult = _optionalElseExprNode.Evaluate(evaluateParams);
            }

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

            if ((caseResult.GetType() != _resultType) && (_isNumericResult))
            {
                return(CoercerFactory.CoerceBoxed(caseResult, _resultType));
            }
            return(caseResult);
        }
Exemplo n.º 14
0
 public static MultiKeyUntyped GetMultiKey(EventBean theEvent,
                                           IList <EventPropertyGetter> propertyGetters,
                                           IList <Type> coercionTypes)
 {
     Object[] keyValues = GetPropertyArray(theEvent, propertyGetters);
     if (coercionTypes == null)
     {
         return(new MultiKeyUntyped(keyValues));
     }
     for (int i = 0; i < coercionTypes.Count; i++)
     {
         Object key = keyValues[i];
         if ((key != null) && (!Equals(key.GetType(), coercionTypes[i])))
         {
             if (key.IsNumber())
             {
                 key          = CoercerFactory.CoerceBoxed(key, coercionTypes[i]);
                 keyValues[i] = key;
             }
         }
     }
     return(new MultiKeyUntyped(keyValues));
 }
Exemplo n.º 15
0
        private Object EvaluateCaseSyntax1(EventBean[] eventsPerStream, bool isNewData, ExprEvaluatorContext exprEvaluatorContext)
        {
            // Case 1 expression example:
            //      case when a=b then x [when c=d then y...] [else y]

            Object caseResult = null;
            bool   matched    = false;

            foreach (UniformPair <ExprEvaluator> p in _whenThenNodeList)
            {
                var whenResult = (bool?)p.First.Evaluate(new EvaluateParams(eventsPerStream, isNewData, exprEvaluatorContext));

                // If the 'when'-expression returns true
                if (whenResult ?? false)
                {
                    caseResult = p.Second.Evaluate(new EvaluateParams(eventsPerStream, isNewData, exprEvaluatorContext));
                    matched    = true;
                    break;
                }
            }

            if ((!matched) && (_optionalElseExprNode != null))
            {
                caseResult = _optionalElseExprNode.Evaluate(new EvaluateParams(eventsPerStream, isNewData, exprEvaluatorContext));
            }

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

            if ((caseResult.GetType() != _resultType) && (_isNumericResult))
            {
                return(CoercerFactory.CoerceBoxed(caseResult, _resultType));
            }
            return(caseResult);
        }
Exemplo n.º 16
0
 public static MultiKeyUntyped GetMultiKey(EventBean[] eventsPerStream,
                                           ExprEvaluator[] evaluators,
                                           ExprEvaluatorContext context,
                                           IList <Type> coercionTypes)
 {
     Object[] keyValues = GetPropertyArray(eventsPerStream, evaluators, context);
     if (coercionTypes == null)
     {
         return(new MultiKeyUntyped(keyValues));
     }
     for (int i = 0; i < coercionTypes.Count; i++)
     {
         Object key = keyValues[i];
         if ((key != null) && (!Equals(key.GetType(), coercionTypes[i])))
         {
             if (key.IsNumber())
             {
                 key          = CoercerFactory.CoerceBoxed(key, coercionTypes[i]);
                 keyValues[i] = key;
             }
         }
     }
     return(new MultiKeyUntyped(keyValues));
 }
Exemplo n.º 17
0
        public Object Get(EventBean eventBean)
        {
            var und = eventBean.Underlying;

            if (und == null)
            {
                throw new PropertyAccessException("Unexpected null underlying event encountered, expecting System.Xml.XmlNode instance as underlying");
            }

            XPathNavigator navigator;

            var xnode = und as XElement;

            if (xnode == null)
            {
                var node = und as XmlNode;
                if (node == null)
                {
                    throw new PropertyAccessException("Unexpected underlying event of type '" + und.GetType().FullName +
                                                      "' encountered, expecting System.Xml.XmlNode as underlying");
                }

                if (Log.IsDebugEnabled)
                {
                    Log.Debug(
                        "Running XPath '{0}' for property '{1}' against Node XML : {2}",
                        _expressionText,
                        _property,
                        SchemaUtil.Serialize((XmlNode)und));
                }

                navigator = node.CreateNavigator();
            }
            else
            {
                navigator = xnode.CreateNavigator();
            }

            try
            {
                var result = navigator.Evaluate(_expression);
                if (result == null)
                {
                    return(null);
                }

                // if there is no parser, return xpath expression type
                if (_optionalCastToType == null)
                {
                    var nodeIterator = result as XPathNodeIterator;
                    if (nodeIterator != null)
                    {
                        if (nodeIterator.Count == 0)
                        {
                            return(null);
                        }
                        if (nodeIterator.Count == 1)
                        {
                            nodeIterator.MoveNext();
                            switch (_resultType)
                            {
                            case XPathResultType.Any:
                                return(((System.Xml.IHasXmlNode)nodeIterator.Current).GetNode());

                            case XPathResultType.String:
                                return(nodeIterator.Current.TypedValue);

                            case XPathResultType.Boolean:
                                return(nodeIterator.Current.ValueAsBoolean);

                            case XPathResultType.Number:
                                return(nodeIterator.Current.ValueAsDouble);

                            default:
                                return(nodeIterator.Current.TypedValue);
                            }
                        }
                        else
                        {
                            return(new XPathIteratorNodeList(nodeIterator));
                        }
                    }

                    return(result);
                }

                if (_isCastToArray)
                {
                    return(CastToArray(result));
                }

                if (result is XPathNodeIterator)
                {
                    var nodeIterator = result as XPathNodeIterator;
                    if (nodeIterator.Count == 0)
                    {
                        return(null);
                    }
                    if (nodeIterator.Count == 1)
                    {
                        nodeIterator.MoveNext();
                        result = nodeIterator.Current.TypedValue;
                    }
                    else
                    {
                        if (_simpleTypeParser == null)
                        {
                            var resultList = new List <object>();
                            while (nodeIterator.MoveNext())
                            {
                                result = nodeIterator.Current.TypedValue;
                                resultList.Add(result);
                            }

                            return(resultList.ToArray());
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }
                }

                // string results get parsed
                if (result is String)
                {
                    try
                    {
                        return(_simpleTypeParser.Invoke((string)result));
                    }
                    catch
                    {
                        Log.Warn("Error parsing XPath property named '" + _property + "' expression result '" + result + " as type " + _optionalCastToType.Name);
                        return(null);
                    }
                }

                // coercion
                if (result is Double)
                {
                    try
                    {
                        return(CoercerFactory.CoerceBoxed(result, _optionalCastToType));
                    }
                    catch
                    {
                        Log.Warn("Error coercing XPath property named '" + _property + "' expression result '" + result + " as type " + _optionalCastToType.Name);
                        return(null);
                    }
                }

                // check bool type
                if (result is Boolean)
                {
                    if (_optionalCastToType != typeof(bool?))
                    {
                        Log.Warn("Error coercing XPath property named '" + _property + "' expression result '" + result + " as type " + _optionalCastToType.Name);
                        return(null);
                    }
                    return(result);
                }

                Log.Warn("Error processing XPath property named '" + _property + "' expression result '" + result + ", not a known type");
                return(null);
            }
            catch (XPathException e) {
                throw new PropertyAccessException("Error getting property " + _property, e);
            }
        }
Exemplo n.º 18
0
        /// <summary>
        /// Write new variable values and commit, evaluating assignment expressions using the given
        /// events per stream.
        /// <para />Populates an optional map of new values if a non-null map is passed.
        /// </summary>
        /// <param name="variableService">variable service</param>
        /// <param name="eventsPerStream">events per stream</param>
        /// <param name="valuesWritten">null or an empty map to populate with written values</param>
        /// <param name="exprEvaluatorContext">expression evaluation context</param>
        public void WriteVariables(VariableService variableService,
                                   EventBean[] eventsPerStream,
                                   IDictionary <String, Object> valuesWritten,
                                   ExprEvaluatorContext exprEvaluatorContext)
        {
            ISet <String> variablesBeansCopied = null;

            if (!_copyMethods.IsEmpty())
            {
                variablesBeansCopied = new HashSet <String>();
            }

            // We obtain a write lock global to the variable space
            // Since expressions can contain variables themselves, these need to be unchangeable for the duration
            // as there could be multiple statements that do "var1 = var1 + 1".
            using (variableService.ReadWriteLock.AcquireWriteLock())
            {
                try
                {
                    variableService.SetLocalVersion();

                    var count = 0;
                    foreach (var assignment in _assignments)
                    {
                        var variableMetaData = _metaData[count];
                        int agentInstanceId  = variableMetaData.ContextPartitionName == null ? EPStatementStartMethodConst.DEFAULT_AGENT_INSTANCE_ID : exprEvaluatorContext.AgentInstanceId;
                        var value            = assignment.Evaluator.Evaluate(
                            new EvaluateParams(eventsPerStream, true, exprEvaluatorContext));

                        if (_writers[count] != null)
                        {
                            var reader = variableService.GetReader(
                                variableMetaData.VariableName, exprEvaluatorContext.AgentInstanceId);
                            var current = (EventBean)reader.Value;
                            if (current == null)
                            {
                                value = null;
                            }
                            else
                            {
                                var writeDesc = _writers[count];
                                var copy      = variablesBeansCopied.Add(writeDesc.VariableName);
                                if (copy)
                                {
                                    var copied = _copyMethods.Get(writeDesc.Type).Copy(current);
                                    current = copied;
                                }
                                variableService.Write(variableMetaData.VariableNumber, agentInstanceId, current);
                                writeDesc.Writer.Write(value, current);
                            }
                        }
                        else if (variableMetaData.EventType != null)
                        {
                            var eventBean = _eventAdapterService.AdapterForType(value, variableMetaData.EventType);
                            variableService.Write(variableMetaData.VariableNumber, agentInstanceId, eventBean);
                        }
                        else
                        {
                            if ((value != null) && (_mustCoerce[count]))
                            {
                                value = CoercerFactory.CoerceBoxed(value, variableMetaData.VariableType);
                            }
                            variableService.Write(variableMetaData.VariableNumber, agentInstanceId, value);
                        }

                        count++;

                        if (valuesWritten != null)
                        {
                            valuesWritten.Put(assignment.VariableName, value);
                        }
                    }

                    variableService.Commit();
                }
                catch (Exception ex)
                {
                    Log.Error("Error evaluating on-set variable expressions: " + ex.Message, ex);
                    variableService.Rollback();
                }
            }
        }
Exemplo n.º 19
0
        private void CreateNewVariable(String variableName, String optionalContextName, Type type, EventType eventType, bool constant, Object value)
        {
            lock (this)
            {
                // check type
                var variableType = type.GetBoxedType();

                // check if it exists
                var metaData = _variables.Get(variableName);
                if (metaData != null)
                {
                    throw new VariableExistsException(VariableServiceUtil.GetAlreadyDeclaredEx(variableName, false));
                }

                // find empty spot
                var emptySpot = -1;
                var count     = 0;
                foreach (var entry in _variableVersionsPerCP)
                {
                    if (entry == null)
                    {
                        emptySpot = count;
                        break;
                    }
                    count++;
                }

                int variableNumber;
                if (emptySpot != -1)
                {
                    variableNumber = emptySpot;
                    _variableVersionsPerCP[emptySpot] = new ConcurrentDictionary <int, VariableReader>();
                    _changeCallbacksPerCP[emptySpot]  = null;
                }
                else
                {
                    variableNumber = _currentVariableNumber;
                    _variableVersionsPerCP.Add(new ConcurrentDictionary <int, VariableReader>());
                    _changeCallbacksPerCP.Add(null);
                    _currentVariableNumber++;
                }

                // check coercion
                var coercedValue = value;
                if (eventType != null)
                {
                    if ((value != null) && (!TypeHelper.IsSubclassOrImplementsInterface(value.GetType(), eventType.UnderlyingType)))
                    {
                        throw new VariableTypeException("Variable '" + variableName
                                                        + "' of declared event type '" + eventType.Name + "' underlying type '" + eventType.UnderlyingType.FullName +
                                                        "' cannot be assigned a value of type '" + value.GetType().FullName + "'");
                    }
                    coercedValue = _eventAdapterService.AdapterForType(value, eventType);
                }
                else if (variableType == typeof(object))
                {
                    // no validation
                }
                else
                {
                    // allow string assignments to non-string variables
                    if ((coercedValue != null) && (coercedValue is String))
                    {
                        try {
                            coercedValue = TypeHelper.Parse(variableType, (String)coercedValue);
                        }
                        catch (Exception ex)
                        {
                            throw new VariableTypeException(
                                      string.Format(
                                          "Variable '{0}' of declared type {1} cannot be initialized by value '{2}': {3}: {4}",
                                          variableName,
                                          variableType.GetTypeNameFullyQualPretty(),
                                          coercedValue,
                                          ex.GetType().FullName,
                                          ex.Message));
                        }
                    }

                    if ((coercedValue != null) && (variableType.GetBoxedType() != coercedValue.GetBoxedType()))
                    {
                        // if the declared type is not numeric or the init value is not numeric, fail
                        if ((!variableType.IsNumeric()) || (!(coercedValue.IsNumber())))
                        {
                            throw GetVariableTypeException(variableName, variableType, coercedValue.GetType());
                        }

                        if (!(coercedValue.GetType().CanCoerce(variableType)))
                        {
                            throw GetVariableTypeException(variableName, variableType, coercedValue.GetType());
                        }
                        // coerce
                        coercedValue = CoercerFactory.CoerceBoxed(coercedValue, variableType);
                    }
                }

                var initialState = coercedValue;
                VariableStateFactory stateFactory = new VariableStateFactoryConst(initialState);

                metaData = new VariableMetaData(variableName, optionalContextName, variableNumber, variableType, eventType, constant, stateFactory);
                _variables.Put(variableName, metaData);
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// NOTE: Code-generation-invoked method, method name and parameter order matters
        /// </summary>
        /// <param name="navigator">The navigator.</param>
        /// <param name="expression">The expression.</param>
        /// <param name="expressionText">The expression text.</param>
        /// <param name="property">The property.</param>
        /// <param name="optionalCastToType">Type of the optional cast to.</param>
        /// <param name="resultType">Type of the result.</param>
        /// <param name="isCastToArray">if set to <c>true</c> [is cast to array].</param>
        /// <param name="simpleTypeParser">The simple type parser.</param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        /// <exception cref="PropertyAccessException">Error getting property " + property</exception>
        public static Object EvaluateXPathGet(
            XPathNavigator navigator,
            XPathExpression expression,
            String expressionText,
            String property,
            Type optionalCastToType,
            XPathResultType resultType,
            bool isCastToArray,
            SimpleTypeParser simpleTypeParser)
        {
            try
            {
                var result = navigator.Evaluate(expression);
                if (result == null)
                {
                    return(null);
                }

                // if there is no parser, return xpath expression type
                if (optionalCastToType == null)
                {
                    var nodeIterator = result as XPathNodeIterator;
                    if (nodeIterator != null)
                    {
                        if (nodeIterator.Count == 0)
                        {
                            return(null);
                        }
                        if (nodeIterator.Count == 1)
                        {
                            nodeIterator.MoveNext();
                            switch (resultType)
                            {
                            case XPathResultType.Any:
                                return(((System.Xml.IHasXmlNode)nodeIterator.Current).GetNode());

                            case XPathResultType.String:
                                return(nodeIterator.Current.TypedValue);

                            case XPathResultType.Boolean:
                                return(nodeIterator.Current.ValueAsBoolean);

                            case XPathResultType.Number:
                                return(nodeIterator.Current.ValueAsDouble);

                            default:
                                return(nodeIterator.Current.TypedValue);
                            }
                        }
                        else
                        {
                            return(new XPathIteratorNodeList(nodeIterator));
                        }
                    }

                    return(result);
                }

                if (isCastToArray)
                {
                    return(CastToArray(result, optionalCastToType, simpleTypeParser, expression));
                }

                if (result is XPathNodeIterator)
                {
                    var nodeIterator = result as XPathNodeIterator;
                    if (nodeIterator.Count == 0)
                    {
                        return(null);
                    }
                    if (nodeIterator.Count == 1)
                    {
                        nodeIterator.MoveNext();
                        result = nodeIterator.Current.TypedValue;
                    }
                    else
                    {
                        if (simpleTypeParser == null)
                        {
                            var resultList = new List <object>();
                            while (nodeIterator.MoveNext())
                            {
                                result = nodeIterator.Current.TypedValue;
                                resultList.Add(result);
                            }

                            return(resultList.ToArray());
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }
                }

                // string results get parsed
                if (result is String)
                {
                    try
                    {
                        return(simpleTypeParser.Invoke((string)result));
                    }
                    catch
                    {
                        Log.Warn("Error parsing XPath property named '" + property + "' expression result '" + result + " as type " + optionalCastToType.Name);
                        return(null);
                    }
                }

                // coercion
                if (result is Double)
                {
                    try
                    {
                        return(CoercerFactory.CoerceBoxed(result, optionalCastToType));
                    }
                    catch
                    {
                        Log.Warn("Error coercing XPath property named '" + property + "' expression result '" + result + " as type " + optionalCastToType.Name);
                        return(null);
                    }
                }

                // check bool type
                if (result is Boolean)
                {
                    if (optionalCastToType != typeof(bool?))
                    {
                        Log.Warn("Error coercing XPath property named '" + property + "' expression result '" + result + " as type " + optionalCastToType.Name);
                        return(null);
                    }
                    return(result);
                }

                Log.Warn("Error processing XPath property named '" + property + "' expression result '" + result + ", not a known type");
                return(null);
            }
            catch (XPathException e)
            {
                throw new PropertyAccessException("Error getting property " + property, e);
            }
        }