论坛首页 编程语言技术论坛

简单el表达式实现

浏览 2771 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-06-21  

一个简单的el表达式实现

 

实现还在完善种,现在只能处理引用类型的的属性字段和函数,不支持容器类数组!不支持子类型

 

线来个测试用例

 

package com.isnowfox.oel;

import java.util.Date;

import com.isnowfox.core.junit.BaseTest;
import com.isnowfox.util.RandomUtils;

/**
 * el 测试用例
 * @author zuoge85
 *
 */
public class OelTest extends BaseTest{
	public void testBasObject() throws UnknownKeyException{
		OelEngine oel = OelEngine.getInstance();
		TestObject obj = new TestObject();
		Date date = new Date();
		int number = RandomUtils.randInt();
		String string = "测试用例";
		
		obj.dateField =date;
		obj.setDateProperty(date);
		
		obj.intField =number;
		obj.setIntProperty(number);
		
		obj.stringField = string;
		obj.setStringProperty(string);
		
		obj.dateMethod(date);
		
		assertEquals(date, oel.el(obj, "dateProperty"));
		assertEquals(date.getTime(), oel.el(obj, "dateProperty.time"));
		assertEquals(date, oel.el(obj, "dateField"));
		assertEquals(date.getTime(), oel.el(obj, "dateField.time"));
		assertEquals(date, oel.el(obj, "dateMethod()"));
		assertEquals(date.getTime(), oel.el(obj, "dateMethod().time"));
		
		assertEquals(number, oel.el(obj, "intField"));
		assertEquals(number, oel.el(obj, "intProperty"));
		
		assertEquals(string, oel.el(obj, "stringField"));
		assertEquals(string, oel.el(obj, "stringProperty"));
		
		
		
	}
}

 

package com.isnowfox.oel;

import java.util.Date;

public class TestObject {
	public int intField;
	public String stringField;
	public Date dateField;
	private int intProperty;
	private String StringProperty;
	private Date dateProperty;
	private Date dateMethod;
	public int getIntProperty() {
		return intProperty;
	}
	public void setIntProperty(int intProperty) {
		this.intProperty = intProperty;
	}
	public String getStringProperty() {
		return StringProperty;
	}
	public void setStringProperty(String stringProperty) {
		StringProperty = stringProperty;
	}
	public Date getDateProperty() {
		return dateProperty;
	}
	public void setDateProperty(Date dateProperty) {
		this.dateProperty = dateProperty;
	}
	public Date dateMethod(){
		return dateMethod;
	}
	public void dateMethod(Date dateMethod){
		this.dateMethod = dateMethod;
	}
	@Override
	public String toString() {
		return "TestObject [intField=" + intField + ", StringField="
				+ stringField + ", dataField=" + dateField + ", intProperty="
				+ intProperty + ", StringProperty=" + StringProperty
				+ ", dataProperty=" + dateProperty + "]";
	}
}

 

 

下面是实现

 

package com.isnowfox.oel;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;

import com.isnowfox.oel.KeyInfo.Type;

/**
 * oel引擎
 * @author zuoge85
 *
 */
public class OelEngine {
	private static final boolean DEBUG = true;
	
	private static final String PACKAGE_NAME = OelEngine.class.getPackage().getName();
	private static Map<Class<?>, Class<?>> primitivesWrapMap = new HashMap<Class<?>, Class<?>>(16);
	static{
		primitivesWrapMap.put(boolean.class, Boolean.class);
		primitivesWrapMap.put(byte.class, Byte.class);
		primitivesWrapMap.put(char.class, Character.class);
		primitivesWrapMap.put(double.class, Double.class);
		primitivesWrapMap.put(float.class, Float.class);
		primitivesWrapMap.put(int.class, Integer.class);
		primitivesWrapMap.put(long.class, Long.class);
		primitivesWrapMap.put(short.class, Short.class);
		primitivesWrapMap.put( void.class, Void.class);
	}
	
	public static final OelEngine getInstance(){
		return Inner.instance;
	}
	
	private Map<String,OelProxy> cacheMap = new HashMap<>();
	
	private AtomicInteger itemSeed = new AtomicInteger();
	public Object el(Object obj,String el) throws UnknownKeyException{
		if(obj == null){
			throw new NullPointerException("null");
		}
		try {
			Class<?> cls = obj.getClass();
			String cacheKey = cls.getName() + el;
			OelProxy p =cacheMap.get(cacheKey);
			if(p==null){
				ClassPool pool = ClassPool.getDefault();
				CtClass cc = pool.makeClass(PACKAGE_NAME + ".MyOelProxy" + itemSeed.incrementAndGet()); 
				cc.addInterface(pool.get(PACKAGE_NAME +".OelProxy"));
				CtMethod method = CtNewMethod.make("public Object el(Object obj);", cc);
				method.setBody(makeMethod(cls, obj, el));
				cc.addMethod(method);
				if(DEBUG){
					cc.debugWriteFile("debug");
				}
				p =  (OelProxy) cc.toClass().newInstance();
				cacheMap.put(cacheKey, p);
			}
			return p.el(obj);
		} catch (NotFoundException|CannotCompileException|InstantiationException|IllegalAccessException e) {
			throw new RuntimeException(e);
		} 
	}
	
	private String makeMethod(Class<?> cls, Object obj, String el) throws UnknownKeyException{
		int varSeed = 0;
		StringBuilder sb = new StringBuilder("{\n");
		String[] keys = el.split("\\.");
		sb.append(cls.getCanonicalName() + " var_" + (++varSeed) + " = (" +cls.getCanonicalName() + ")$1;\n" );
		for(String key:keys){
			KeyInfo info =analyse(cls,key);
			int nextVar = varSeed++ ;
			switch (info.getType()) {
			case FIELD:
				sb.append(info.getCls().getCanonicalName() +" var_" + varSeed + " = var_"+ nextVar +"." + key + ";\n");
				break;
			case PROPERTY:
				sb.append(info.getCls().getCanonicalName() +" var_" + varSeed + " = var_"+ nextVar +"." + info.getMethodName() + "();\n");
				break;
			case METHOD:
				sb.append(info.getCls().getCanonicalName() +" var_" + varSeed + " = var_"+ nextVar +"." + key + ";\n");
				break;
			default:
				break;
			}
			cls = info.getCls();
		}
		if(cls.isPrimitive()){
			cls = wrap(cls);
			sb.append("return "+cls.getCanonicalName()+".valueOf(var_" + varSeed + ");}");
		}else{
			sb.append("return var_" + varSeed + ";}");
		}
		return sb.toString();
	}
	
	private KeyInfo analyse(Class<?> cls,String key) throws UnknownKeyException{
		try {
			if(key.endsWith("()")){
				try {
					Method method = cls.getMethod(key.substring(0, key.length()-2));
					return new KeyInfo(Type.METHOD, method.getReturnType());
				} catch (Exception e2) {
					
				}
			}
			PropertyDescriptor prop = new PropertyDescriptor(key, cls);
			return new KeyInfo(Type.PROPERTY, prop.getPropertyType(), prop.getReadMethod().getName());
		} catch (IntrospectionException e) {
			//属性没找到那么可能是field
			Field field;
			try {
				field = cls.getField(key);
				return new KeyInfo(Type.FIELD, field.getType());
			} catch (Exception e1) {
				
			}
		}
		throw new UnknownKeyException("未知的 key:"+key +",cls:"+ cls);
	}
	private Class<?> wrap(Class<?> cls){
		return primitivesWrapMap.get(cls);
	}
	public Object part(Object Obj,String name){
		return null;
	}
	
	private static class Inner{
		private static final OelEngine instance = new OelEngine();
	}
}

 

 

 

   发表时间:2013-06-21  
在做BBS,来个测试
0 请登录后投票
   发表时间:2013-06-21  
BBS测试2
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics