private Object forIterator()

in src/main/java/org/apache/commons/jexl3/internal/Interpreter.java [694:769]


    private Object forIterator(final ASTForeachStatement node, final Object data) {
        Object result = null;
        /* first objectNode is the loop variable */
        final ASTReference loopReference = (ASTReference) node.jjtGetChild(0);
        final ASTIdentifier loopVariable = (ASTIdentifier) loopReference.jjtGetChild(0);
        final int symbol = loopVariable.getSymbol();
        final boolean lexical = loopVariable.isLexical() || options.isLexical();
        final LexicalFrame locals = lexical? new LexicalFrame(frame, block) : null;
        final boolean loopSymbol = symbol >= 0 && loopVariable instanceof ASTVar;
        if (lexical) {
            // create lexical frame
            // it may be a local previously declared
            if (loopSymbol && !defineVariable((ASTVar) loopVariable, locals)) {
                return redefinedVariable(node, loopVariable.getName());
            }
            block = locals;
        }
        Object forEach = null;
        try {
            /* second objectNode is the variable to iterate */
            final Object iterableValue = node.jjtGetChild(1).jjtAccept(this, data);
            // make sure there is a value to iterate upon
            if (iterableValue == null) {
                return null;
            }
            /* last child node is the statement to execute */
            final int numChildren = node.jjtGetNumChildren();
            final JexlNode statement = numChildren >= 3 ? node.jjtGetChild(numChildren - 1) : null;
            // get an iterator for the collection/array/etc. via the introspector.
            forEach = operators.tryOverload(node, JexlOperator.FOR_EACH, iterableValue);
            final Iterator<?> itemsIterator = forEach instanceof Iterator
                    ? (Iterator<?>) forEach
                    : uberspect.getIterator(iterableValue);
            if (itemsIterator == null) {
                return null;
            }
            int cnt = 0;
            while (itemsIterator.hasNext()) {
                cancelCheck(node);
                // reset loop variable
                if (lexical && cnt++ > 0) {
                    // clean up but remain current
                    block.pop();
                    // unlikely to fail
                    if (loopSymbol && !defineVariable((ASTVar) loopVariable, locals)) {
                        return redefinedVariable(node, loopVariable.getName());
                    }
                }
                // set loopVariable to value of iterator
                final Object value = itemsIterator.next();
                if (symbol < 0) {
                    setContextVariable(node, loopVariable.getName(), value);
                } else {
                    frame.set(symbol, value);
                }
                if (statement != null) {
                    try {
                        // execute statement
                        result = statement.jjtAccept(this, data);
                    } catch (final JexlException.Break stmtBreak) {
                        break;
                    } catch (final JexlException.Continue stmtContinue) {
                        //continue;
                    }
                }
            }
        } finally {
            //  closeable iterator handling
            closeIfSupported(forEach);
            // restore lexical frame
            if (lexical) {
                block = block.pop();
            }
        }
        return result;
    }