package com.aggrepoint.winlet.jsp;
import java.beans.FeatureDescriptor;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.PropertyNotFoundException;
import javax.el.PropertyNotWritableException;
import javax.persistence.Entity;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.core.annotation.AnnotationUtils;
import com.aggrepoint.winlet.ConfigProvider;
import com.aggrepoint.winlet.ContextUtils;
import com.aggrepoint.winlet.HashMapWrapper;
import com.aggrepoint.winlet.ListProvider;
import com.aggrepoint.winlet.ListProviderWrapper;
import com.aggrepoint.winlet.PageStorage;
import com.aggrepoint.winlet.SharedPageStorage;
import com.aggrepoint.winlet.WinletEl;
import com.aggrepoint.winlet.spring.WinletDefaultFormattingConversionService;
import com.aggrepoint.winlet.spring.annotation.Winlet;
import com.aggrepoint.winlet.utils.BeanProperty;
import com.aggrepoint.winlet.utils.EncodeUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
/**
* 支持在EL中通过w.访问Winlet对象,通过ps.访问Page Storage,通过ret.访问响应码对象,通过win访问taglib功能等
*
* @author Jiangming Yang (yangjm@gmail.com)
*/
public class Resolver extends javax.el.ELResolver {
static Hashtable<String, BeanProperty> m_htProperties = new Hashtable<String, BeanProperty>();
static public Object getObjectValue(Object obj, String property)
throws Exception {
String key = obj.getClass() + "_" + property.toString();
// Try to get property from cache
BeanProperty bp = m_htProperties.get(key);
if (bp != null) {
return bp.get(obj);
} else {
bp = new BeanProperty(obj.getClass(), property, true, false);
m_htProperties.put(key, bp);
return bp.get(obj);
}
}
@Override
public Class<?> getCommonPropertyType(ELContext arg0, Object arg1) {
return null;
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext arg0,
Object arg1) {
return null;
}
@Override
public Class<?> getType(ELContext context, Object base, Object property)
throws NullPointerException, PropertyNotFoundException, ELException {
return null;
}
public static String lineBreakToHtml(String str) {
try {
if (str == null)
return "";
return str.replace("
", "<br>").replace("
", "<br>")
.replace("
", "<br>");
} catch (Exception e) {
return str;
}
}
@Override
public Object getValue(ELContext context, Object base, Object property)
throws NullPointerException, PropertyNotFoundException, ELException {
Object val = null;
if (base == null) {
if (property.equals("r")) {
val = ContextUtils.getReqInfo().getReturnDef();
} else if (property.equals("req")) {
val = ContextUtils.getReqInfo();
} else if (property.equals("reqid")) {
val = ContextUtils.getReqInfo().getRequestId();
} else if (property.equals("sps")) {
val = ContextUtils.getReqInfo().getSharedPageStorage();
} else if (property.equals("ps")) {
val = ContextUtils.getReqInfo().getPageStorage();
} else if (property.equals("prule")) {
val = ContextUtils.getPsnRuleEngine(ContextUtils.getRequest());
} else if (property.equals("arule")) {
val = ContextUtils.getAccessRuleEngine(ContextUtils
.getRequest());
} else if (property.equals("u")) {
val = ContextUtils.getUser(ContextUtils.getRequest());
} else if (property.equals("c")) { // config provider
val = ContextUtils.getConfigProvider(ContextUtils.getRequest());
} else if (property.equals("m")) { // object map
val = ContextUtils.getListProvider(ContextUtils.getRequest());
} else if (property.equals("cm")) { // code value map
val = new ListProviderWrapper(1,
ContextUtils.getListProvider(ContextUtils.getRequest()));
} else if (property.equals("l")) { // object list
val = new ListProviderWrapper(2,
ContextUtils.getListProvider(ContextUtils.getRequest()));
} else if (property.equals("cl")) { // code value list
val = new ListProviderWrapper(3,
ContextUtils.getListProvider(ContextUtils.getRequest()));
} else if (property.equals("f")) {
// val = ThreadContext.getAttribute(THREAD_ATTR_REQUEST);
} else if (property.equals("e")) {
// val = ThreadContext.getAttribute(THREAD_ATTR_EXCEPTION);
} else if (property.equals("win"))
val = new WinletEl();
if (val != null)
context.setPropertyResolved(true);
} else {
if (base instanceof PageStorage) {
val = ((PageStorage) base).getAttribute(property);
context.setPropertyResolved(true);
} else if (base instanceof SharedPageStorage) {
val = ((SharedPageStorage) base).getAttribute(property);
context.setPropertyResolved(true);
} else if (base instanceof ConfigProvider) {
val = ((ConfigProvider) base).getStr(property.toString());
context.setPropertyResolved(true);
} else if (base instanceof ListProviderWrapper) {
switch (((ListProviderWrapper) base).getType()) {
case 1:
val = ((ListProvider) base).getCodeValueMap(property
.toString());
context.setPropertyResolved(true);
break;
case 2:
val = ((ListProvider) base).getList(property.toString());
context.setPropertyResolved(true);
break;
case 3:
val = ((ListProvider) base).getCodeValueList(property
.toString());
context.setPropertyResolved(true);
break;
}
} else if (base instanceof ListProvider) {
val = ((ListProvider) base).getMap(property.toString());
context.setPropertyResolved(true);
} else if (base instanceof WinletEl) {
WinletEl winEl = (WinletEl) base;
if (winEl.getMethod() == null) {
winEl.setMethod(property.toString());
val = winEl;
} else {
val = winEl.execute(property.toString());
context.setPropertyResolved(true);
}
} else if (base instanceof HashMapWrapper) {
val = ((HashMapWrapper<?, ?>) base).get(property.toString());
context.setPropertyResolved(true);
} else if (base instanceof JsonNode) {
JsonNode node = ((JsonNode) base).get(property.toString());
val = node;
if (node != null) {
if (node.isNull()) {
val = null;
} else if (node.isArray() && node instanceof ArrayNode) {
List<JsonNode> dst = new ArrayList<JsonNode>();
for (Iterator<JsonNode> it = ((ArrayNode) node)
.elements(); it.hasNext();)
dst.add(it.next());
val = dst;
} else if (node.isInt())
val = node.asInt();
else if (node.isBigDecimal() || node.isDouble()
|| node.isFloatingPointNumber())
val = node.asDouble();
else if (node.isBoolean())
val = node.asBoolean();
else if (node.isBigInteger() || node.isLong())
val = node.asLong();
else if (node.isTextual())
val = node.asText();
}
context.setPropertyResolved(true);
} else {
if (AnnotationUtils.findAnnotation(base.getClass(),
Winlet.class) != null) {
try {
val = getObjectValue(base, property.toString());
context.setPropertyResolved(true);
} catch (Exception e) {
}
} else if (property.toString().indexOf(".") == -1
&& WinletDefaultFormattingConversionService.canFormat(
base, property.toString())) {
// Apply format annotation declared on fields
val = WinletDefaultFormattingConversionService.format(base,
property.toString());
context.setPropertyResolved(true);
} else if ((AnnotationUtils.findAnnotation(base.getClass(),
Entity.class) != null || AnnotationUtils
.findAnnotation(base.getClass(), EncodeString.class) != null)
&& String.class.equals(getPropType(base,
property.toString()))) {
// 如果是Entity的属性并且类型为字符串则加上encoding,并且将换行转换为<br>
val = lineBreakToHtml(EncodeUtils.html(new BeanWrapperImpl(
base).getPropertyValue(property.toString())));
context.setPropertyResolved(true);
}
}
}
return val;
}
static Hashtable<String, Class<?>> PROP_TYPES = new Hashtable<String, Class<?>>();
static Class<?> getPropType(Object obj, String prop) {
String key = obj.getClass().getName() + "_" + prop;
if (!PROP_TYPES.containsKey(key)) {
Class<?> type = new BeanWrapperImpl(obj).getPropertyType(prop);
if (type == null)
return null;
PROP_TYPES.put(key, type);
}
return PROP_TYPES.get(key);
}
@Override
public boolean isReadOnly(ELContext arg0, Object arg1, Object arg2)
throws NullPointerException, PropertyNotFoundException, ELException {
return false;
}
@Override
public void setValue(ELContext arg0, Object arg1, Object arg2, Object arg3)
throws NullPointerException, PropertyNotFoundException,
PropertyNotWritableException, ELException {
}
}