コード例 #1
0
        protected internal override IValueRef GetValueRef(ExpressionState state)
        {
            if (ChildCount == 1)
            {
                return(_children[0].GetValueRef(state));
            }

            var nextNode = _children[0];

            try
            {
                var result = nextNode.GetValueInternal(state);
                var cc     = ChildCount;
                for (var i = 1; i < cc - 1; i++)
                {
                    try
                    {
                        state.PushActiveContextObject(result);
                        nextNode = _children[i];

                        result = nextNode.GetValueInternal(state);
                    }
                    finally
                    {
                        state.PopActiveContextObject();
                    }
                }

                try
                {
                    state.PushActiveContextObject(result);
                    nextNode = _children[cc - 1];
                    return(nextNode.GetValueRef(state));
                }
                finally
                {
                    state.PopActiveContextObject();
                }
            }
            catch (SpelEvaluationException ex)
            {
                // Correct the position for the error before re-throwing
                ex.Position = nextNode.StartPosition;
                throw;
            }
        }
コード例 #2
0
        private object[] GetArguments(ExpressionState state)
        {
            var arguments = new object[ChildCount];

            for (var i = 0; i < arguments.Length; i++)
            {
                // Make the root object the active context again for evaluating the parameter expressions
                try
                {
                    state.PushActiveContextObject(state.GetScopeRootContextObject());
                    arguments[i] = _children[i].GetValueInternal(state).Value;
                }
                finally
                {
                    state.PopActiveContextObject();
                }
            }

            return(arguments);
        }
コード例 #3
0
ファイル: Selection.cs プロジェクト: SteeltoeOSS/Steeltoe
        protected internal override IValueRef GetValueRef(ExpressionState state)
        {
            var op                = state.GetActiveContextObject();
            var operand           = op.Value;
            var selectionCriteria = _children[0];

            if (operand is System.Collections.IDictionary mapdata)
            {
                // Don't lose generic info for the new map
                var    result  = new Dictionary <object, object>();
                object lastKey = null;

                foreach (DictionaryEntry entry in mapdata)
                {
                    try
                    {
                        var kvPair = new TypedValue(entry);
                        state.PushActiveContextObject(kvPair);
                        state.EnterScope();
                        var val = selectionCriteria.GetValueInternal(state).Value;
                        if (val is bool boolean)
                        {
                            if (boolean)
                            {
                                if (_variant == FIRST)
                                {
                                    result[entry.Key] = entry.Value;
                                    return(new TypedValueHolderValueRef(new TypedValue(result), this));
                                }

                                result[entry.Key] = entry.Value;
                                lastKey           = entry.Key;
                            }
                        }
                        else
                        {
                            throw new SpelEvaluationException(selectionCriteria.StartPosition, SpelMessage.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);
                        }
                    }
                    finally
                    {
                        state.PopActiveContextObject();
                        state.ExitScope();
                    }
                }

                if ((_variant == FIRST || _variant == LAST) && result.Count == 0)
                {
                    return(new TypedValueHolderValueRef(new TypedValue(null), this));
                }

                if (_variant == LAST)
                {
                    var resultMap = new Dictionary <object, object>();
                    result.TryGetValue(lastKey, out var lastValue);
                    resultMap[lastKey] = lastValue;
                    return(new TypedValueHolderValueRef(new TypedValue(resultMap), this));
                }

                return(new TypedValueHolderValueRef(new TypedValue(result), this));
            }

            if (operand is IEnumerable)
            {
                var operandAsArray = operand as Array;
                var data           = operand as IEnumerable;

                var result = new List <object>();
                var index  = 0;
                foreach (var element in data)
                {
                    try
                    {
                        state.PushActiveContextObject(new TypedValue(element));
                        state.EnterScope("index", index);
                        var val = selectionCriteria.GetValueInternal(state).Value;
                        if (val is bool boolean)
                        {
                            if (boolean)
                            {
                                if (_variant == FIRST)
                                {
                                    return(new TypedValueHolderValueRef(new TypedValue(element), this));
                                }

                                result.Add(element);
                            }
                        }
                        else
                        {
                            throw new SpelEvaluationException(selectionCriteria.StartPosition, SpelMessage.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);
                        }

                        index++;
                    }
                    finally
                    {
                        state.ExitScope();
                        state.PopActiveContextObject();
                    }
                }

                if ((_variant == FIRST || _variant == LAST) && result.Count == 0)
                {
                    return(NullValueRef.INSTANCE);
                }

                if (_variant == LAST)
                {
                    var lastElem = result == null || result.Count == 0 ? null : result[result.Count - 1];
                    return(new TypedValueHolderValueRef(new TypedValue(lastElem), this));
                }

                if (operand is IEnumerable && operandAsArray == null)
                {
                    return(new TypedValueHolderValueRef(new TypedValue(result), this));
                }

                // Array
                if (operandAsArray != null)
                {
                    Type elementType = null;
                    var  typeDesc    = op.TypeDescriptor;
                    if (typeDesc != null)
                    {
                        elementType = ReflectionHelper.GetElementTypeDescriptor(typeDesc);
                    }

                    if (elementType == null)
                    {
                        throw new InvalidOperationException("Unresolvable element type");
                    }

                    var resultArray = Array.CreateInstance(elementType, result.Count);
                    Array.Copy(result.ToArray(), 0, resultArray, 0, result.Count);
                    return(new TypedValueHolderValueRef(new TypedValue(resultArray), this));
                }
            }

            if (operand == null)
            {
                if (_nullSafe)
                {
                    return(NullValueRef.INSTANCE);
                }

                throw new SpelEvaluationException(StartPosition, SpelMessage.INVALID_TYPE_FOR_SELECTION, "null");
            }

            throw new SpelEvaluationException(StartPosition, SpelMessage.INVALID_TYPE_FOR_SELECTION, operand.GetType().FullName);
        }
コード例 #4
0
ファイル: Indexer.cs プロジェクト: SteeltoeOSS/Steeltoe
        protected internal override IValueRef GetValueRef(ExpressionState state)
        {
            var         context          = state.GetActiveContextObject();
            var         target           = context.Value;
            var         targetDescriptor = context.TypeDescriptor;
            ITypedValue indexValue;
            object      index;

            // This first part of the if clause prevents a 'double dereference' of the property (SPR-5847)
            if (target is System.Collections.IDictionary && (_children[0] is PropertyOrFieldReference reference1))
            {
                var reference = reference1;
                index      = reference.Name;
                indexValue = new TypedValue(index);
            }
            else
            {
                // In case the map key is unqualified, we want it evaluated against the root object
                // so temporarily push that on whilst evaluating the key
                try
                {
                    state.PushActiveContextObject(state.RootContextObject);
                    indexValue = _children[0].GetValueInternal(state);
                    index      = indexValue.Value;
                    if (index == null)
                    {
                        throw new InvalidOperationException("No index");
                    }
                }
                finally
                {
                    state.PopActiveContextObject();
                }
            }

            // Raise a proper exception in case of a null target
            if (target == null)
            {
                throw new SpelEvaluationException(StartPosition, SpelMessage.CANNOT_INDEX_INTO_NULL_VALUE);
            }

            // At this point, we need a TypeDescriptor for a non-null target object
            if (targetDescriptor == null)
            {
                throw new InvalidOperationException("No type descriptor");
            }

            // Indexing into a Map
            if (target is System.Collections.IDictionary)
            {
                var key        = index;
                var mapkeyType = ReflectionHelper.GetMapKeyTypeDescriptor(targetDescriptor);
                if (mapkeyType != null)
                {
                    key = state.ConvertValue(key, mapkeyType);
                }

                _indexedType = IndexedType.MAP;
                return(new MapIndexingValueRef(this, state.TypeConverter, (IDictionary)target, key, targetDescriptor));
            }

            // If the object is something that looks indexable by an integer,
            // attempt to treat the index value as a number
            if (target is Array || target is IList || target is string)
            {
                var idx = (int)state.ConvertValue(index, typeof(int));
                if (target is Array)
                {
                    _indexedType = IndexedType.ARRAY;
                    return(new ArrayIndexingValueRef(this, state.TypeConverter, target, idx, targetDescriptor));
                }
                else if (target is IList list)
                {
                    _indexedType = IndexedType.LIST;

                    return(new CollectionIndexingValueRef(this, list, idx, targetDescriptor, state.TypeConverter, state.Configuration.AutoGrowCollections, state.Configuration.MaximumAutoGrowSize));
                }
                else
                {
                    _indexedType = IndexedType.STRING;
                    return(new StringIndexingLValue(this, (string)target, idx, targetDescriptor));
                }
            }

            // Try and treat the index value as a property of the context object
            // Could call the conversion service to convert the value to a String
            var valueType = indexValue.TypeDescriptor;

            if (valueType != null && typeof(string) == valueType)
            {
                _indexedType = IndexedType.OBJECT;
                return(new PropertyIndexingValueRef(this, target, (string)index, state.EvaluationContext, targetDescriptor));
            }

            throw new SpelEvaluationException(StartPosition, SpelMessage.INDEXING_NOT_SUPPORTED_FOR_TYPE, targetDescriptor);
        }
コード例 #5
0
ファイル: Projection.cs プロジェクト: kimbell/Steeltoe
        protected internal override IValueRef GetValueRef(ExpressionState state)
        {
            var op = state.GetActiveContextObject();

            var operand        = op.Value;
            var operandAsArray = operand as Array;

            // TypeDescriptor operandTypeDescriptor = op.getTypeDescriptor();

            // When the input is a map, we push a special context object on the stack
            // before calling the specified operation. This special context object
            // has two fields 'key' and 'value' that refer to the map entries key
            // and value, and they can be referenced in the operation
            // eg. {'a':'y','b':'n'}.![value=='y'?key:null]" == ['a', null]
            if (operand is IDictionary)
            {
                var mapData = (IDictionary)operand;
                var result  = new List <object>();
                foreach (var entry in mapData)
                {
                    try
                    {
                        state.PushActiveContextObject(new TypedValue(entry));
                        state.EnterScope();
                        result.Add(_children[0].GetValueInternal(state).Value);
                    }
                    finally
                    {
                        state.PopActiveContextObject();
                        state.ExitScope();
                    }
                }

                return(new TypedValueHolderValueRef(new TypedValue(result), this));  // TODO unable to build correct type descriptor
            }

            if (operand is IEnumerable)
            {
                var data = operand as IEnumerable;

                var  result           = new List <object>();
                Type arrayElementType = null;
                foreach (var element in data)
                {
                    try
                    {
                        state.PushActiveContextObject(new TypedValue(element));
                        state.EnterScope("index", result.Count);
                        var value = _children[0].GetValueInternal(state).Value;
                        if (value != null && operandAsArray != null)
                        {
                            arrayElementType = DetermineCommonType(arrayElementType, value.GetType());
                        }

                        result.Add(value);
                    }
                    finally
                    {
                        state.ExitScope();
                        state.PopActiveContextObject();
                    }
                }

                if (operandAsArray != null)
                {
                    if (arrayElementType == null)
                    {
                        arrayElementType = typeof(object);
                    }

                    var resultArray = Array.CreateInstance(arrayElementType, result.Count);
                    Array.Copy(result.ToArray(), 0, resultArray, 0, result.Count);
                    return(new TypedValueHolderValueRef(new TypedValue(resultArray), this));
                }

                return(new TypedValueHolderValueRef(new TypedValue(result), this));
            }

            if (operand == null)
            {
                if (_nullSafe)
                {
                    return(NullValueRef.INSTANCE);
                }

                throw new SpelEvaluationException(StartPosition, SpelMessage.PROJECTION_NOT_SUPPORTED_ON_TYPE, "null");
            }

            throw new SpelEvaluationException(StartPosition, SpelMessage.PROJECTION_NOT_SUPPORTED_ON_TYPE, operand.GetType().FullName);
        }