All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mvel.templates.res.ForEachNode Maven / Gradle / Ivy

The newest version!
package org.mvel.templates.res;

import org.mvel.util.StringAppender;
import org.mvel.util.PropertyTools;
import static org.mvel.util.PropertyTools.createStringTrimmed;
import org.mvel.integration.VariableResolverFactory;
import org.mvel.integration.impl.MapVariableResolverFactory;
import org.mvel.MVEL;
import org.mvel.CompileException;
import org.mvel.templates.TemplateSyntaxError;
import org.mvel.templates.TemplateRuntimeError;
import org.mvel.templates.TemplateRuntime;
import org.mvel.templates.util.ArrayIterator;

import java.util.*;

public class ForEachNode extends Node {
    public Node nestedNode;

    private String[] item;
    private String[] expression;

    private char[] sepExpr;

    public ForEachNode() {
    }

    public ForEachNode(int begin, String name, char[] template, int start, int end) {
        super(begin, name, template, start, end);
        configure();
    }

    public Node getNestedNode() {
        return nestedNode;
    }

    public void setNestedNode(Node nestedNode) {
        this.nestedNode = nestedNode;
    }

    public boolean demarcate(Node terminatingnode, char[] template) {
        nestedNode = next;
        next = terminus;

        sepExpr = terminatingnode.getContents();
        if (sepExpr.length == 0) sepExpr = null;

        return false;
    }

    public Object eval(TemplateRuntime runtime, StringAppender appender, Object ctx, VariableResolverFactory factory) {
        Iterator[] iters = new Iterator[item.length];

        Object o;
        for (int i = 0; i < iters.length; i++) {
            if ((o = MVEL.eval(expression[i], ctx, factory)) instanceof Collection) {
                iters[i] = ((Collection) o).iterator();
            }
            else if (o instanceof Object[]) {
                iters[i] = new ArrayIterator((Object[]) o);
            }
            else {
                throw new TemplateRuntimeError("cannot iterate object type: " + o.getClass().getName());
            }
        }

        Map locals = new HashMap();
        MapVariableResolverFactory localFactory = new MapVariableResolverFactory(locals, factory);

        int iterate = iters.length;

        while (true) {
            for (int i = 0; i < iters.length; i++) {
                if (!iters[i].hasNext()) {
                    iterate--;
                    locals.put(item[i], "");
                }
                else {
                    locals.put(item[i], iters[i].next());
                }
            }
            if (iterate != 0) {
                nestedNode.eval(runtime, appender, ctx, localFactory);

                if (sepExpr != null) {
                    for (Iterator it : iters) {
                        if (it.hasNext()) {
                            appender.append(MVEL.eval(sepExpr, ctx, factory));
                            break;
                        }
                    }
                }
            }
            else break;
        }

        return next != null ? next.eval(runtime, appender, ctx, factory) : null;
    }

    private void configure() {
        ArrayList items = new ArrayList();
        ArrayList expr = new ArrayList();

        int start = 0;
        for (int i = 0; i < contents.length; i++) {
            switch (contents[i]) {
                case ':':
                    items.add(createStringTrimmed(contents, start, i - start));
                    start = i + 1;
                    break;
                case ',':
                    if (expr.size() != (items.size() - 1)) {
                        throw new CompileException("unexpected character ',' in foreach tag", cStart + i);
                    }
                    expr.add(createStringTrimmed(contents, start, i - start));
                    start = i + 1;
                    break;
            }
        }

        if (start < contents.length) {
            if (expr.size() != (items.size() - 1)) {
                throw new CompileException("expected character ':' in foreach tag", cEnd);
            }
            expr.add(createStringTrimmed(contents, start, contents.length - start));
        }

        item = new String[items.size()];
        int i = 0;
        for (String s : items) item[i++] = s;

        expression = new String[expr.size()];
        i = 0;
        for (String s : expr) expression[i++] = s;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy