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

net.sf.jxls.reader.ExpressionCollectionParser Maven / Gradle / Ivy

package net.sf.jxls.reader;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.parser.ASTIdentifier;
import org.apache.commons.jexl2.parser.ASTReference;
import org.apache.commons.jexl2.parser.Node;
import org.apache.commons.jexl2.parser.Parser;
import org.apache.commons.jexl2.parser.SimpleNode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ExpressionCollectionParser {
    protected final Log log = LogFactory.getLog(getClass());

    public final static String COLLECTION_REFERENCE_SUFFIX = "_JxLsC_";

    // This is set up as a ThreadLocal parser to avoid threading issues.
    private static ThreadLocal parser = new ThreadLocal() {
        protected synchronized Object initialValue() {
            return new Parser(new StringReader(";"));
        }
    };

    private boolean jexlInnerCollectionsAccess;

    private String collectionExpression;
    private Collection collection;

    public ExpressionCollectionParser(JexlContext jexlContext, String expr, boolean jexlInnerCollectionsAccess) {
        try {
            this.jexlInnerCollectionsAccess = jexlInnerCollectionsAccess;
            SimpleNode tree = ((Parser) parser.get()).parse(new StringReader(expr), null);
            ArrayList references = new ArrayList();
            findReferences(references, tree);
            findCollection(jexlContext, references);
        } catch (Exception e) {
            log.error("Can't parse jexl expression " + expr);
            throw new RuntimeException("Can't parse jexl expression", e);
        }
    }

    public String getCollectionExpression() {
        return collectionExpression;
    }

    public Collection getCollection() {
        return collection;
    }

    private void findReferences(List references, Node node) {

        if (node instanceof ASTReference) {
            references.add(node);
        }

        int childCount = node.jjtGetNumChildren();
        for (int i = 0; i < childCount; i++) {
            findReferences(references, node.jjtGetChild(i));
        }
    }

    private void findCollection(JexlContext jexlContext, List references) {

        Node node;

        for (Iterator itr = references.iterator(); itr.hasNext();) {
            node = (Node) itr.next();
            String expression = findCollectionProperties(jexlContext, node);
            if (expression != null) {
                if (!expression.endsWith(ExpressionCollectionParser.COLLECTION_REFERENCE_SUFFIX)) {
                    collectionExpression = expression;
                }
                break;
            }
        }
    }

    private String findCollectionProperties(JexlContext jexlContext, Node node) {

        int childCount = node.jjtGetNumChildren();
        Node child;
        String subExpr = null;

        JexlEngine jexlEngine = new JexlEngine();
        for (int i = 0; i < childCount; i++) {
            child = node.jjtGetChild(i);
            if (child instanceof ASTIdentifier) {
                ASTIdentifier ident = (ASTIdentifier) child;
                if (subExpr == null) {
                    subExpr = ident.image;
                } else {
                    subExpr = subExpr + "." + ident.image;
                }
                if (jexlInnerCollectionsAccess) {
                    if (subExpr.endsWith(ExpressionCollectionParser.COLLECTION_REFERENCE_SUFFIX)) {
                        return subExpr;
                    }
                }
                try {
                    Expression e = jexlEngine.createExpression(subExpr);
                    Object obj = e.evaluate(jexlContext);
                    if (obj instanceof Collection) {
                        this.collection = (Collection) obj;
                        return subExpr;
                    }
                } catch (Exception e) {
                    // TODO: insert proper logging here
                    return null;
                }
            }
        }

        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy