package com.google.code.joto.value2java.converters; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import com.google.code.joto.ast.beanstmt.BeanAST.BeanExpr; import com.google.code.joto.ast.beanstmt.BeanAST.ClassExpr; import com.google.code.joto.ast.beanstmt.BeanAST.LiteralExpr; import com.google.code.joto.ast.beanstmt.BeanAST.MethodApplyExpr; import com.google.code.joto.ast.beanstmt.BeanAST.NewArrayExpr; import com.google.code.joto.ast.valueholder.ValueHolderAST.AbstractObjectValueHolder; import com.google.code.joto.ast.valueholder.ValueHolderAST.ImmutableObjectValueHolder; import com.google.code.joto.reflect.ReflectUtils; import com.google.code.joto.value2java.ObjectVHToStmtConverter; import com.google.code.joto.value2java.VHToStmt; import com.google.code.joto.value2java.VHToStmtConverterLookup; import com.google.code.joto.value2java.impl.ObjectStmtInfo; /** * converters for ObjectValueHolder to Stmt, * representing internal (immutable) jre objects: java.lang. / java.lang.reflect objects.. */ public class JavaLangVHToStmtConverters { private static final StringConverter StringConverterInstance = new StringConverter(); private static final ClassConverter ClassConverterInstance = new ClassConverter(); private static final MethodConverter MethodConverterInstance = new MethodConverter(); public static void registerDefaultConverters(VHToStmtConverterLookup p) { p.registerConverter(StringConverterInstance, 0); p.registerConverter(ClassConverterInstance, 0); p.registerConverter(MethodConverterInstance, 0); } // ------------------------------------------------------------------------- public static abstract class AbstractJavaLangVHToStmtConverter implements ObjectVHToStmtConverter { private final Class<?> type; protected AbstractJavaLangVHToStmtConverter(Class<?> type) { super(); this.type = type; } @Override public boolean canConvert(Class<?> type) { return this.type == type; } @Override public void convert(VHToStmt owner, AbstractObjectValueHolder obj, ObjectStmtInfo objInfo) { if (!(obj instanceof ImmutableObjectValueHolder)) { throw new IllegalArgumentException(); } ImmutableObjectValueHolder vh = (ImmutableObjectValueHolder) obj; Object value = vh.getValue(); BeanExpr expr = doConvertValue(owner, obj, objInfo, value); objInfo.setTypeAndInitExpr(value.getClass(), expr); } protected abstract BeanExpr doConvertValue(VHToStmt owner, AbstractObjectValueHolder obj, ObjectStmtInfo objInfo, Object value); @Override public String toString() { String simpleName = type.getSimpleName(); return simpleName + "VHToStmtConverter[]"; } } /** * */ public static class StringConverter extends AbstractJavaLangVHToStmtConverter { protected StringConverter() { super(String.class); } @Override protected BeanExpr doConvertValue(VHToStmt owner, AbstractObjectValueHolder obj, ObjectStmtInfo objInfo, Object value) { return new LiteralExpr(value); } } /** * */ public static class ClassConverter extends AbstractJavaLangVHToStmtConverter { protected ClassConverter() { super(Class.class); } @Override protected BeanExpr doConvertValue(VHToStmt owner, AbstractObjectValueHolder obj, ObjectStmtInfo objInfo, Object value) { Class<?> clss = (Class<?>) value; String simpleName = clss.getSimpleName(); // todo use fully qualified name instead?? return new ClassExpr(simpleName); } } /** * */ public static class MethodConverter extends AbstractJavaLangVHToStmtConverter { protected MethodConverter() { super(Method.class); } @Override protected BeanExpr doConvertValue(VHToStmt owner, AbstractObjectValueHolder obj, ObjectStmtInfo objInfo, Object value) { Method meth = (Method) value; Class<?> declClass = meth.getDeclaringClass(); String methodName = meth.getName(); // test if method name is unique in parent class to generate simple resolver code List<Method> methodsByName = ReflectUtils.findMethodsByName(declClass, methodName, false); boolean isUniqByName = (methodsByName.size() == 1); List<BeanExpr> args = new ArrayList<BeanExpr>(); args.add(new LiteralExpr(methodName)); if (!isUniqByName) { // not uniq => <<className>>.class.getMethod(<<methodName>>, new Class[] { type0, type1, ...typeN}); Class<?>[] paramTypes = meth.getParameterTypes(); BeanExpr[] paramTypeExprs = new BeanExpr[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) { String paramTypeName = paramTypes[i].getSimpleName(); // TOCHECK use simple name... paramTypeExprs[i] = new ClassExpr(paramTypeName); } args.add(new NewArrayExpr(Class.class, paramTypes.length, paramTypeExprs)); } // else uniq => <<className>>.class.getMethod(<<methodName>>); String simpleDeclaringClassName = declClass.getSimpleName(); // todo use fully qualified name instead?? return new MethodApplyExpr(new ClassExpr(simpleDeclaringClassName), "getMethod", args); } } }