修改net.sf.jxls.parser包下的
Expression
package net.sf.jxls.parser;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.sf.jxls.transformer.Configuration;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;
/**
* Represents JEXL expression
* @author Leonid Vysochyn
*/
public class Expression {
public static final String aggregateSeparator = "[a-zA-Z()]+[0-9]*:";
String expression;
String rawExpression;
String aggregateFunction;
String aggregateField;
Map beans;
List properties = new ArrayList();
org.apache.commons.jexl2.Expression jexlExpresssion;
Configuration config;
Property collectionProperty;
public Property getCollectionProperty() {
return collectionProperty;
}
public List getProperties() {
return properties;
}
public String getExpression() {
return expression;
}
public Expression(String expression, Configuration config) {
this.expression = expression;
this.config = config;
}
public Expression(String expression, Map beans, Configuration config) throws Exception {
this.config = config;
this.expression = expression;
this.rawExpression = parseAggregate(expression);
this.beans = beans;
//修改表达式 创建方法
JexlEngine JEXL = new JexlEngine();
jexlExpresssion = JEXL.createExpression("map."+rawExpression);
// jexlExpresssion = ExpressionFactory.createExpression( rawExpression );
parse();
}
private void parse() {
Property prop = new Property(rawExpression, beans, config);
this.properties = new ArrayList();
this.properties.add(prop);
if (prop.isCollection() && aggregateFunction == null && collectionProperty == null) {
this.collectionProperty = prop;
}
}
public Object evaluate() throws Exception {
if (beans != null && !beans.isEmpty()){
/*-------------------开始修改------------------------------*/
org.apache.commons.jexl2.JexlContext jc = new MapContext();
jc.set("map", beans); //jexl 2 开始必须要名称 默认设置一个名称map
Object ret = jexlExpresssion.evaluate(jc);
JexlEngine JEXL1 = new JexlEngine();
org.apache.commons.jexl2.Expression e = JEXL1.createExpression("map."+rawExpression);//在表达式中增加 我在前面设置的名称 map
Object ret1 = jexlExpresssion.evaluate(jc);
/*-------------------结束修改------------------------------*/
if (aggregateFunction != null) {
return calculateAggregate(aggregateFunction, aggregateField, ret);
}
return ret;
}
return expression;
}
private String parseAggregate(String expr)
{
String[] aggregateParts = expr.split(aggregateSeparator, 2);
int i = expr.indexOf(":");
if (aggregateParts.length >= 2 && i >= 0) {
String aggregate = expr.substring(0, i);
if (aggregate.length() == 0) {
aggregateFunction = null;
aggregateField = null;
}
else {
int f1 = aggregate.indexOf("(");
int f2 = aggregate.indexOf(")");
if (f1 != -1 && f2 != -1 && f2 > f1) {
aggregateFunction = aggregate.substring(0, f1);
aggregateField = aggregate.substring(f1+1, f2);
}
else {
aggregateFunction = aggregate;
aggregateField = "c1";
}
}
return expr.substring(i+1);
}
aggregateFunction = null;
aggregateField = null;
return expr;
}
private Object calculateAggregate(String function, String field, Object list)
{
Aggregator agg = Aggregator.getInstance(function);
if (agg != null) {
if (list instanceof Collection) {
Collection coll = (Collection) list;
for (Iterator iterator = coll.iterator(); iterator.hasNext();) {
Object o = iterator.next();
try {
Object f = PropertyUtils.getProperty(o, field);
agg.add(f);
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
else {
try {
Object f = PropertyUtils.getProperty(list, field);
agg.add(f);
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return agg.getResult();
}
return list;
}
public String toString() {
return expression;
}
}
ExpressionCollectionParser
package net.sf.jxls.parser;
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;
public class ExpressionCollectionParser {
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(org.apache.commons.jexl2.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) {
e.printStackTrace();
}
}
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 newExpression = findCollectionProperties(jexlContext, node);
if (newExpression != null) {
if (!newExpression.endsWith(COLLECTION_REFERENCE_SUFFIX)) {
this.collectionExpression = newExpression;
}
break;
}
}
}
private String findCollectionProperties(JexlContext jexlContext, Node node) {
int childCount = node.jjtGetNumChildren();
Node child ;
String subExpr = null;
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(COLLECTION_REFERENCE_SUFFIX)) {
return subExpr;
}
}
try {
JexlEngine JEXL = new JexlEngine();
Expression e = JEXL.createExpression("map."+subExpr);
// Expression e = ExpressionFactory.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;
}
}
Property
package net.sf.jxls.parser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import net.sf.jxls.transformer.Configuration;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.MapContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Represents a property in excel template
* @author Leonid Vysochyn
*/
public class Property {
protected final Log log = LogFactory.getLog(getClass());
List propertyTokens = new ArrayList();
private String beanName;
private Object bean;
private String collectionName;
private Collection collection;
private String property;
private Object propertyValue;
Configuration config;
public Property(String value) {
propertyValue = value;
}
public Property(String property, Map beans, Configuration config) {
this.property = property;
this.config = config;
propertyValue = getPropertyValue(beans);
}
public boolean isConstant(){
return property==null;
}
public Object getPropertyValue(Map beans) {
JexlContext jc = new MapContext();
jc.set("map", beans);
// JexlContext context = JexlHelper.createContext();
// context.setVars(beans);
ExpressionCollectionParser parser = new ExpressionCollectionParser(jc,this.property + ";", config.isJexlInnerCollectionsAccess());
if (parser.getCollection() == null) {
propertyValue = null;
} else {
collectionName = parser.getCollectionExpression();
collection = parser.getCollection();
beanName = null;
bean = null;
}
return propertyValue;
}
public boolean isCollection() {
return collectionName != null;
}
public boolean isNull() {
return getPropertyValue() == null;
}
public String getBeanName() {
return beanName;
}
public String getCollectionName() {
return collectionName;
}
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
public String getProperty() {
return property;
}
public Collection getCollection() {
return collection;
}
public void setCollection(Collection collection) {
this.collection = collection;
}
public String getFullCollectionName() {
if (beanName == null) {
return collectionName;
}
return beanName + "." + collectionName;
}
public String getPropertyNameAfterLastDot() {
String propertyName = null;
if (property != null) {
int dotIndex = property.lastIndexOf(".");
if (dotIndex >= 0) {
propertyName = property.substring(dotIndex + 1);
} else {
propertyName = property;
}
}
return propertyName;
}
public String getPropertyNameAfterFirstDot() {
String propertyName = null;
if (property != null) {
int dotIndex = property.indexOf(".");
if (dotIndex >= 0) {
propertyName = property.substring(dotIndex + 1);
} else {
propertyName = property;
}
}
return propertyName;
}
public String toString() {
return "Property{" +
"property='" + property + "'}";
}
public Object getPropertyValue() {
if( bean instanceof String){
return bean;
}
return propertyValue;
}
public void setPropertyValue(Object propertyValue) {
this.propertyValue = propertyValue;
}
public Object getBean() {
return bean;
}
public void setBean(Object bean) {
this.bean = bean;
}
}