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

gu.sql2java.TableManagerDecorator Maven / Gradle / Ivy

There is a newer version: 5.2.0
Show newest version
package gu.sql2java;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import static com.google.common.base.Preconditions.*;
import static gu.sql2java.NameUtilities.*;
import static com.google.common.base.MoreObjects.*;
import static gu.sql2java.SimpleLog.*;
import static gu.sql2java.Managers.*;

/**
 * 基于{@link BaseTableManager}实例代理实现接口 
* * @author guyadong * * @param 接口类型 */ public class TableManagerDecorator> implements InvocationHandler{ private final Class interfaceClass; final BaseTableManager delegate; private final Map invokers = Maps.newLinkedHashMap(); @SuppressWarnings("rawtypes") private final Class implClass; final RowMetaData metaData; private static boolean debug = false; /** * 构造方法 * * @param interfaceClass 接口类 * @param delegate 实现接口的实例 */ TableManagerDecorator(Class interfaceClass, BaseTableManager delegate) { checkType(interfaceClass,delegate); this.interfaceClass = interfaceClass; this.delegate = delegate; this.implClass = delegate.getClass(); this.metaData = delegate.metaData; try { compile(); } catch (Exception e) { Throwables.throwIfUnchecked(e); throw new RuntimeException(e); } } /** * 构造方法 * * @param interfaceClass 接口类 * @param tablename 接口类对应的表名 */ TableManagerDecorator(Class interfaceClass, String tablename) { this(interfaceClass,new BaseTableManager(tablename)); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return checkNotNull(invokers.get(method),"UNSUPPORT method %s",method).invoke(args); } /** * @return 根据当前对象创建新的接口实例{@link Proxy} */ public final I proxyInstance(){ return interfaceClass.cast(Proxy.newProxyInstance( interfaceClass.getClassLoader(), new Class[]{ interfaceClass}, this)); } @Override public String toString(){ StringBuffer builder = new StringBuffer(); String simulateClassName = interfaceClass.getSimpleName() + "Decorator"; String simulateTableManagerClass = BaseTableManager.class.getName() + "<" + metaData.beanType.getName() + ">"; builder.append("class ").append(simulateClassName).append(" implements ").append(interfaceClass.getName()).append("{\n"); builder.append(" private final ").append(simulateTableManagerClass).append(" delegate;\n"); builder.append(" public ").append(simulateClassName).append("(").append(simulateTableManagerClass).append(" delegate){\n"); builder.append(" this.delegate = delegate\n"); builder.append(" }\n"); for(Invoker invoker:invokers.values()){ builder.append(invoker); } builder.append("}\n"); return builder.toString(); } /** * 检查参数类型合法性,不匹配则抛出异常 * @param interfaceClass * @param delegate */ private static void checkType(Class interfaceClass, BaseTableManager delegate){ checkArgument(interfaceClass != null, "interfaceClass is null"); checkArgument(delegate != null, "delegate is null"); checkArgument(delegate.metaData.managerInterfaceClass.equals(interfaceClass), "MISMATCH interface class of delegate(%s) with %s", delegate.metaData.managerInterfaceClass.getSimpleName(), interfaceClass.getName()); } /** * 创建{@code interfaceClass}接口实例 * @param interfaceClass 接口类 * @param delegate 代理类实例 * @return {@code interfaceClass}接口实例 */ static final >I makeInterfaceInstance(Class interfaceClass,BaseTableManager delegate){ return new TableManagerDecorator(interfaceClass,delegate).proxyInstance(); } /** * 创建{@code interfaceClass}接口实例 * @param interfaceClass 接口类 * @param tablename 接口类对应的表名 * @return {@code interfaceClass}接口实例 */ static final >I makeInterfaceInstance(Class interfaceClass,String tablename){ return new TableManagerDecorator(interfaceClass,tablename).proxyInstance(); } /** * 创建接口实例 * @param delegate 代理类实例 * @return 接口实例 */ static final >TableManager makeInterfaceInstance(BaseTableManager delegate){ checkArgument(delegate != null ,"delegate is null"); checkArgument(delegate.metaData.managerInterfaceClass != null,"delegate.metaData.managerInterfaceClass is null"); return makeInterfaceInstance(delegate.metaData.managerInterfaceClass,delegate); } /** * 创建接口实例 * @param tablename 接口类对应的表名 * @return 接口实例 */ static final >TableManager makeInterfaceInstance(String tablename){ return makeInterfaceInstance(getBaseTableManager(tablename)); } /** * 设置是否输出调试信息标志 * @param debug */ static void setDebug(boolean debug) { TableManagerDecorator.debug = debug; } private static final String M_LOADBYPRIMARYKEY = "loadByPrimaryKey"; private static final String D_LOADBYPKS = "loadByPks"; private static final String M_LOADBYPRIMARYKEYCHECKED = "loadByPrimaryKeyChecked"; private static final String M_EXISTSPRIMARYKEY = "existsPrimaryKey"; private static final String M_CHECKDUPLICATE = "checkDuplicate"; private static final String D_CHECKDUPLICATEBYPK = "checkDuplicateByPk"; private static final String M_DELETEBYPRIMARYKEY = "deleteByPrimaryKey"; private static final String D_DELETEBYPKS = "deleteByPks"; private static final String M_TOPRIMARYKEYLIST = "toPrimaryKeyList"; private static final String P_ADDJUNCTION = "addJunction(With(\\w+))?"; private static final String D_ADDJUNCTION = "addJunction"; private static final String P_DELETEJUNCTION = "deleteJunction(With(\\w+))?"; private static final String D_DELETEJUNCTION = "deleteJunction"; private static final String P_GETIMPORTEDBEANS = "get(\\w+)sBy(\\w+)$"; private static final String D_GETIMPORTEDBEANS = "getImportedBeans"; private static final String P_GETIMPORTEDBEANSASLIST = "get(\\w+)sBy(\\w+)AsList"; private static final String D_GETIMPORTEDBEANSASLIST = "getImportedBeansAsList"; private static final String P_DELETEIMPORTEDBEANS = "delete(\\w+)sBy(\\w+)"; private static final String D_DELETEIMPORTEDBEANS = "deleteImportedBeans"; private static final String P_SETIMPORTEDBEANS = "set(\\w+)sBy(\\w+)"; private static final String D_SETIMPORTEDBEANS = "setImportedBeans"; private static final String M_SAVE = "save"; private static final String D_SAVEFULLY = "saveFully"; private static final String M_SAVEASTRANSACTION = "saveAsTransaction"; private static final String D_SAVEFULLYASTRANSACTION = "saveFullyAsTransaction"; private static final String P_GETREFERENCEDBEAN = "getReferencedBy(\\w+)"; private static final String D_GETREFERENCEDBEAN = "getReferencedBean"; private static final String P_SETREFERENCEDBEAN = "setReferencedBy(\\w+)"; private static final String D_SETREFERENCEDBEAN = "setReferencedBean"; private static final String P_LOADBYINDEX = "loadByIndex(\\w+)"; private static final String D_LOADBYINDEX = "loadByIndex"; private static final String P_LOADUNIQUEBYINDEXCHECKED = "loadByIndex(\\w+)Checked"; private static final String D_LOADUNIQUEBYINDEXCHECKED = "loadUniqueByIndexChecked"; private static final String D_LOADBYINDEXFORINDICES = "loadByIndexForIndices"; private static final String D_LOADUNIQUEBYINDEX = "loadUniqueByIndex"; private static final String P_LOADBYINDEXASLIST = "loadByIndex(\\w+)AsList"; private static final String D_LOADBYINDEXASLIST = "loadByIndexAsList"; private static final String P_DELETEBYINDEX = "deleteByIndex(\\w+)"; private static final String D_DELETEBYINDEX = "deleteByIndex"; private static final String P_LOADVIAJUNCTIONASLIST = "loadVia(\\w+)AsList"; private static final String D_LOADVIAJUNCTIONASLIST = "loadViaJunctionAsList"; private static final String P_LISTOFSELFREF = "listOf(\\w+)"; private static final String D_LISTOFSELFREF = "listOfSelfRef"; private static final String P_LEVELOFSELFREF = "levelOf(\\w+)"; private static final String D_LEVELOFSELFREF = "levelOfSelfRef"; private static final String P_ISCYCLEOFSELFREF = "isCycleOn(\\w+)"; private static final String D_ISCYCLEOFSELFREF = "isCycleOfSelfRef"; private static final String P_CHECKCYCLEOFSELFREF = "checkCycleOf(\\w+)"; private static final String D_CHECKCYCLEOFSELFREF = "checkCycleOfSelfRef"; private static final String P_TOPOFSELFREF = "topOf(\\w+)"; private static final String D_TOPOFSELFREF = "topOfSelfRef"; private static final String P_CHILDLISTOFSELFREF = "childListBy(\\w+)"; private static final String D_CHILDLISTOFSELFREF = "childListOfSelfRef"; private static final String P_CHILDRENOFSELFREF = "childrenBy(\\w+)"; private static final String D_CHILDRENOFSELFREF = "childrenOfSelfRef"; private static final String P_CHILDRENOFBEANSOFSELFREF = "childrenOfBeansBy(\\w+)"; private static final String D_CHILDRENOFBEANSOFSELFREF = "childrenOfBeansOfSelfRef"; private static final String P_CHILDRENOFPKSOFSELFREF = "childrenOfPksBy(\\w+)"; private static final String D_CHILDRENOFPKSOFSELFREF = "childrenOfPksOfSelfRef"; private static final Comparator METHOD_COMPARATOR = new Comparator() { @Override public int compare(Method o1, Method o2) { return signatureOf(o1).compareTo(signatureOf(o2)); } }; private static boolean declaredBySuper(Method method,Class superClazz){ if(method.getDeclaringClass().equals(superClazz)){ return true; } for(Class clazz:superClazz.getInterfaces()){ if(declaredBySuper(method,clazz)){ return true; } } return false; } /** * 向上递归查找指定的方法,找不到指定的方法则抛出异常 * @param clazz * @param name * @param parameterTypes * @return 方法对象 * @throws NoSuchMethodException 找不到指定的方法 * @throws SecurityException */ private static Method recursiveGetDeclaredMethod(Class clazz,String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { try { return clazz.getDeclaredMethod(name, parameterTypes); } catch (NoSuchMethodException e) { Class superClass = clazz.getSuperclass(); if(null != superClass){ return recursiveGetDeclaredMethod(superClass,name,parameterTypes); } throw e; } } /** * 在代理类({@link #implClass})查找指定的方法,找不到指定的方法则抛出异常 * @param name * @param parameterTypes * @return 方法对象 * @throws NoSuchMethodException 找不到指定的方法 * @throws SecurityException */ private Method getDeclaredMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { return recursiveGetDeclaredMethod(implClass, name, parameterTypes); } private NoSuchMethodException makeNoSuchMethodException(Method def){ return new NoSuchMethodException(logString("NO FOUND MATCHED METHOD for %s in %s",def,implClass)); } private Invoker compile(Method def) throws NoSuchMethodException, SecurityException{ Method impl; String name = def.getName(); if(declaredBySuper(def,TableManager.class)){ impl = BaseTableManager.class.getDeclaredMethod(name, def.getParameterTypes()); return new MethodInvoker(def, impl, delegate); } switch(name){ case M_LOADBYPRIMARYKEY: return loadByPrimaryKey(def); case M_LOADBYPRIMARYKEYCHECKED: impl = getDeclaredMethod(M_LOADBYPRIMARYKEYCHECKED, Object[].class); return new MethodInvoker(def, impl, delegate); case M_EXISTSPRIMARYKEY: impl = getDeclaredMethod(M_EXISTSPRIMARYKEY, Object[].class); return new MethodInvoker(def, impl, delegate); case M_CHECKDUPLICATE: impl = getDeclaredMethod(D_CHECKDUPLICATEBYPK, Object.class); return new MethodInvoker(def, impl, delegate); case M_DELETEBYPRIMARYKEY: return deleteByPrimaryKey(def); case M_TOPRIMARYKEYLIST: return toPrimaryKeyList(def); case M_SAVE: return saveFully(def); case M_SAVEASTRANSACTION: return saveFullyAsTransaction(def); default: if(name.matches(P_ADDJUNCTION)){ return addJunction(def); } if(name.matches(P_DELETEJUNCTION)){ return deleteJunction(def); } if(name.matches(P_GETIMPORTEDBEANSASLIST)){ return getImportedBeansAsList(def); } if(name.matches(P_GETIMPORTEDBEANS)){ return getImportedBeans(def); } if(name.matches(P_DELETEIMPORTEDBEANS)){ return deleteImportedBeans(def); } if(name.matches(P_SETIMPORTEDBEANS)){ return setImportedBeans(def); } if(name.matches(P_GETREFERENCEDBEAN)){ return getReferencedBean(def); } if(name.matches(P_SETREFERENCEDBEAN)){ return setReferencedBean(def); } if(name.matches(P_LOADBYINDEXASLIST)){ return loadByIndexAsList(def); } if(name.matches(P_LOADUNIQUEBYINDEXCHECKED)){ return loadUniqueByIndexChecked(def); } if(name.matches(P_LOADBYINDEX)){ return loadByIndex(def); } if(name.matches(P_DELETEBYINDEX)){ return deleteByIndex(def); } if(name.matches(P_LOADVIAJUNCTIONASLIST)){ return loadViaJunctionAsList(def); } if(name.matches(P_LISTOFSELFREF)){ return listOfSelfRef(def); } if(name.matches(P_LEVELOFSELFREF)){ return levelOfSelfRef(def); } if(name.matches(P_ISCYCLEOFSELFREF)){ return isCycleOfSelfRef(def); } if(name.matches(P_CHECKCYCLEOFSELFREF)){ return checkCycleOfSelfRef(def); } if(name.matches(P_TOPOFSELFREF)){ return topOfSelfRef(def); } if(name.matches(P_CHILDLISTOFSELFREF)){ return childListOfSelfRef(def); } if(name.matches(P_CHILDRENOFSELFREF)){ return childrenOfSelfRef(def); } if(name.matches(P_CHILDRENOFBEANSOFSELFREF)){ return childrenOfSelfRefForBeans(def); } if(name.matches(P_CHILDRENOFPKSOFSELFREF)){ return childrenOfSelfRefForPks(def); } throw new IllegalArgumentException(logString("NO SUCH METHOD maped %s",def.getName())); } } private void addObjectInvoker(String methodName,Class...parameterTypes) throws NoSuchMethodException, SecurityException{ Method method = Object.class.getMethod(methodName, parameterTypes); ObjectInvoker objectInvoker = new ObjectInvoker(method); invokers.put(method, objectInvoker); if(debug){ log("{}",objectInvoker); } } private void compile(Method[] methods) throws NoSuchMethodException, SecurityException{ Arrays.sort(methods,METHOD_COMPARATOR); for(Method method : methods){ Invoker invokder = compile(method); invokers.put(method, invokder); // Invoker old = invokers.put(method, invokder); // checkState(old == null,"duplicated entry for method %s",signatureOf(method)); if(debug){ log("{}",invokder); } } } private void compile() throws NoSuchMethodException, SecurityException{ addObjectInvoker("toString"); addObjectInvoker("hashCode"); addObjectInvoker("equals",Object.class); compile(TableManager.class.getMethods()); /** 过滤所有桥接方法 */ Method[] noBridgeMethods = Arrays.stream(interfaceClass.getDeclaredMethods()) .filter(m->!m.isBridge()).toArray(Method[]::new); compile(noBridgeMethods); } ////////////////////////////////////// // PRIMARY KEY METHODS ////////////////////////////////////// private MethodInvoker loadByPrimaryKey(Method def) throws NoSuchMethodException, SecurityException{ Method impl; Class[] paramTypes = def.getParameterTypes(); checkArgument(paramTypes.length == metaData.primaryKeyCount,"only %s parameter required for %s",metaData.primaryKeyCount,def); if(Arrays.equals(metaData.primaryKeyTypes, paramTypes)){ impl = getDeclaredMethod(M_LOADBYPRIMARYKEY, Object[].class); }else { if(metaData.primaryKeyCount == 1){ if(Collection.class.isAssignableFrom(paramTypes[0])){ impl = getDeclaredMethod(D_LOADBYPKS, Collection.class); }else{ Class pkType = metaData.columnTypeOf(metaData.primaryKeyIds[0]); Object pkArray = Array.newInstance(pkType, 0); if(paramTypes[0] == pkArray.getClass()){ impl = getDeclaredMethod(D_LOADBYPKS, Object[].class); }else { throw makeNoSuchMethodException(def); } } }else{ throw makeNoSuchMethodException(def); } } return new MethodInvoker(def, impl, delegate); } private MethodInvoker deleteByPrimaryKey(Method def) throws NoSuchMethodException, SecurityException{ Method impl; Class[] paramTypes = def.getParameterTypes(); checkArgument(paramTypes.length == metaData.primaryKeyCount,"%s parameter required for %s",metaData.primaryKeyCount,def); if(Arrays.equals(metaData.primaryKeyTypes, paramTypes)){ impl = getDeclaredMethod(M_DELETEBYPRIMARYKEY, Object[].class); }else { if(Collection.class.isAssignableFrom(paramTypes[0])){ impl = getDeclaredMethod(D_DELETEBYPKS, Collection.class); }else{ Class pkType = metaData.columnTypeOf(metaData.primaryKeyIds[0]); Object pkArray = Array.newInstance(pkType, 0); if(paramTypes[0] == pkArray.getClass()){ impl = getDeclaredMethod(D_DELETEBYPKS, Object[].class); }else { throw makeNoSuchMethodException(def); } } } return new MethodInvoker(def, impl, delegate); } ////////////////////////////////////// // GET/SET IMPORTED KEY BEAN METHOD ////////////////////////////////////// private MethodInvoker getImportedBeans(Method def)throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); Pattern pattern = Pattern.compile(P_GETIMPORTEDBEANS); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_GETIMPORTEDBEANS); String importeBeanName = matcher.group(1); String readableName = matcher.group(2); ForeignKeyMetaData importedKey = RowMetaData.getForeignKey(importeBeanName,readableName, metaData.alias); Method impl = getDeclaredMethod(D_GETIMPORTEDBEANS, paramBuilder().add(importedKey.name.getClass(),paramTypes).normalizeLast(1, Object[].class).build()); return new MethodInvoker(def, impl, delegate, importedKey.name); } private MethodInvoker getImportedBeansAsList(Method def)throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); switch(paramTypes.length){ case 1:{ // DO NOTHING break; } case 3:{ if(BaseBean.class.isAssignableFrom(paramTypes[0]) && int.class == paramTypes[1] && int.class == paramTypes[2]){ // DO NOTHING }else{ paramTypes = new Class[]{Object[].class}; } break; } default:{ paramTypes = new Class[]{Object[].class}; break; } } Pattern pattern = Pattern.compile(P_GETIMPORTEDBEANSASLIST); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_GETIMPORTEDBEANSASLIST); String importeBeanName = matcher.group(1); String readableName = matcher.group(2); ForeignKeyMetaData importedKey = RowMetaData.getForeignKey(importeBeanName,readableName, metaData.alias); Method impl = getDeclaredMethod(D_GETIMPORTEDBEANSASLIST, paramBuilder().add(importedKey.name.getClass(),paramTypes).genericNormalize(1,Object[].class).build()); return new MethodInvoker(def, impl, delegate, importedKey.name); } private MethodInvoker deleteImportedBeans(Method def)throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); Pattern pattern = Pattern.compile(P_DELETEIMPORTEDBEANS); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_DELETEIMPORTEDBEANS); String importeBeanName = matcher.group(1); String readableName = matcher.group(2); ForeignKeyMetaData importedKey = RowMetaData.getForeignKey(importeBeanName,readableName, metaData.alias); Method impl = getDeclaredMethod(D_DELETEIMPORTEDBEANS, paramBuilder().add(importedKey.name.getClass(),paramTypes).normalizeLast(1, Object[].class).build()); return new MethodInvoker(def, impl, delegate, importedKey.name); } private MethodInvoker setImportedBeans(Method def)throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 2,"2 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(P_SETIMPORTEDBEANS); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_SETIMPORTEDBEANS); String importeBeanName = matcher.group(1); String readableName = matcher.group(2); ForeignKeyMetaData importedKey = RowMetaData.getForeignKey(importeBeanName,readableName, metaData.alias); Method impl = getDeclaredMethod(D_SETIMPORTEDBEANS, paramBuilder().add(importedKey.name.getClass(),wrapBaseBean(paramTypes)).build()); return new MethodInvoker(def, impl, delegate, importedKey.name); } //_____________________________________________________________________ // // SAVE //_____________________________________________________________________ private MethodInvoker saveFully(Method def)throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); int paramCount = metaData.foreignKeys.size() + metaData.getImportedKeys().size() + 1; checkArgument(paramTypes.length == paramCount,"%s parameter required for %s",paramCount,def.getName()); Method impl = getDeclaredMethod(D_SAVEFULLY, BaseBean.class,Object[].class); return new SaveFullyInvoker(def, impl); } private MethodInvoker saveFullyAsTransaction(Method def)throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); int paramCount = metaData.foreignKeys.size() + metaData.getImportedKeys().size() + 1; checkArgument(paramTypes.length == paramCount,"%s parameter required for %s",paramCount,def.getName()); Method impl = getDeclaredMethod(D_SAVEFULLYASTRANSACTION, BaseBean.class,Object[].class); return new SaveFullyInvoker(def, impl); } ////////////////////////////////////// // GET/SET FOREIGN KEY BEAN METHOD ////////////////////////////////////// private MethodInvoker getReferencedBean(Method def)throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 1,"only 1 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(P_GETREFERENCEDBEAN); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_GETREFERENCEDBEAN); String readableName = matcher.group(1); ForeignKeyMetaData foreignKey = metaData.getForeignKeyByRn(readableName); Method impl = getDeclaredMethod(D_GETREFERENCEDBEAN, foreignKey.name.getClass(), BaseBean.class); return new MethodInvoker(def, impl, delegate, foreignKey.name); } private MethodInvoker setReferencedBean(Method def)throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 2,"2 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(P_SETREFERENCEDBEAN); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_SETREFERENCEDBEAN); String readableName = matcher.group(1); ForeignKeyMetaData foreignKey = metaData.getForeignKeyByRn(readableName); Method impl = getDeclaredMethod(D_SETREFERENCEDBEAN, paramBuilder().add(foreignKey.name.getClass(),wrapBaseBean(paramTypes)).build()); return new MethodInvoker(def, impl, delegate, foreignKey.name); } //_____________________________________________________________________ // // USING INDICES //_____________________________________________________________________ private MethodInvoker loadByIndex(Method def)throws NoSuchMethodException, SecurityException{ Method impl; Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); Pattern pattern = Pattern.compile(P_LOADBYINDEX); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_LOADBYINDEX); String readableName = matcher.group(1); IndexMetaData index = metaData.getIndexCheckedByRn(readableName); if(index.unique){ Object indexArray = Array.newInstance(metaData.jdbcTypeOf(metaData.indexIdArray(index.name)[0]), 0); if(paramTypes[0].equals(indexArray.getClass()) && index.columns.size() == 1){ impl = getDeclaredMethod(D_LOADBYINDEXFORINDICES, index.name.getClass(), Object[].class); } else if(Collection.class.equals(paramTypes[0]) && index.columns.size() == 1){ impl = getDeclaredMethod(D_LOADBYINDEXFORINDICES, index.name.getClass(), Collection.class); }else if(Arrays.equals(metaData.indexTypeArray(index.name), paramTypes)){ impl = getDeclaredMethod(D_LOADUNIQUEBYINDEX, index.name.getClass(), Object[].class); } else{ throw makeNoSuchMethodException(def); } }else{ impl = getDeclaredMethod(D_LOADBYINDEX, index.name.getClass(), Object[].class); } return new MethodInvoker(def, impl, delegate, index.name); } private MethodInvoker loadUniqueByIndexChecked(Method def)throws NoSuchMethodException, SecurityException{ Method impl; Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); Pattern pattern = Pattern.compile(P_LOADUNIQUEBYINDEXCHECKED); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_LOADUNIQUEBYINDEXCHECKED); String readableName = matcher.group(1); IndexMetaData index = metaData.getIndexCheckedByRn(readableName); if(Arrays.equals(metaData.indexTypeArray(index.name), paramTypes)){ impl = getDeclaredMethod(D_LOADUNIQUEBYINDEXCHECKED, index.name.getClass(), Object[].class); } else{ throw makeNoSuchMethodException(def); } return new MethodInvoker(def, impl, delegate, index.name); } private MethodInvoker loadByIndexAsList(Method def)throws NoSuchMethodException, SecurityException{ String methodName = def.getName(); Pattern pattern = Pattern.compile(P_LOADBYINDEXASLIST); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_LOADBYINDEXASLIST); String readableName = matcher.group(1); IndexMetaData index = metaData.getIndexCheckedByRn(readableName); Method impl = getDeclaredMethod(D_LOADBYINDEXASLIST, index.name.getClass(), Object[].class); return new MethodInvoker(def, impl, delegate, index.name); } private MethodInvoker deleteByIndex(Method def)throws NoSuchMethodException, SecurityException{ String methodName = def.getName(); Pattern pattern = Pattern.compile(P_DELETEBYINDEX); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_DELETEBYINDEX); String readableName = matcher.group(1); IndexMetaData index = metaData.getIndexCheckedByRn(readableName); Method impl = getDeclaredMethod(D_DELETEBYINDEX, index.name.getClass(), Object[].class); return new MethodInvoker(def, impl, delegate, index.name); } //_____________________________________________________________________ // // MANY TO MANY: LOAD OTHER BEAN VIA JUNCTION TABLE //_____________________________________________________________________ private MethodInvoker loadViaJunctionAsList(Method def)throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 1 || paramTypes.length == 3,"1 or 3 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(P_LOADVIAJUNCTIONASLIST); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_LOADVIAJUNCTIONASLIST); String coreClassName = matcher.group(1); String junctionTable = RowMetaData.getRowMetaDataByCoreClassName(coreClassName, metaData.alias).tablename; paramBuilder().add(junctionTable.getClass(),wrapBaseBean(paramTypes)).build(); Method impl = getDeclaredMethod(D_LOADVIAJUNCTIONASLIST, paramBuilder().add(junctionTable.getClass(),wrapBaseBean(paramTypes)).build()); return new MethodInvoker(def, impl, delegate, junctionTable); } private MethodInvoker addJunction(Method def) throws NoSuchMethodException, SecurityException{ String name = def.getName(); Type[] gTypes = def.getGenericParameterTypes(); Class[] paramTypes = def.getParameterTypes(); checkArgument(paramTypes.length == 2,"only 2 parameter required for %s",name); RowMetaData junctionTable = metaData.getJunctionTableFor(gTypes[1]); Method impl = getDeclaredMethod(D_ADDJUNCTION, paramBuilder().add(junctionTable.tablename.getClass(),wrapBaseBean(paramTypes)).build()); return new MethodInvoker(def, impl, delegate, junctionTable.tablename); } private MethodInvoker deleteJunction(Method def) throws NoSuchMethodException, SecurityException{ Type[] gTypes = def.getGenericParameterTypes(); Class[] paramTypes = def.getParameterTypes(); checkArgument(paramTypes.length == 2,"only 2 parameter required for %s",def.getName()); RowMetaData junctionTable = metaData.getJunctionTableFor(gTypes[1]); Method impl = getDeclaredMethod(D_DELETEJUNCTION, paramBuilder().add(junctionTable.tablename.getClass(),wrapBaseBean(paramTypes)).build()); return new MethodInvoker(def, impl, delegate, junctionTable.tablename); } private MethodInvoker toPrimaryKeyList(Method def) throws NoSuchMethodException, SecurityException{ Method impl; Class[] paramTypes = def.getParameterTypes(); Class pkType = metaData.columnTypeOf(metaData.primaryKeyIds[0]); checkArgument(paramTypes.length == 1,"only 1 parameter required for %s",def.getName()); if(Collection.class.isAssignableFrom(paramTypes[0])){ impl = getDeclaredMethod(M_TOPRIMARYKEYLIST, Class.class,Collection.class); }else{ Object beanArray = Array.newInstance(metaData.beanType, 0); if(paramTypes[0] == beanArray.getClass()){ impl = getDeclaredMethod(M_TOPRIMARYKEYLIST, Class.class,BaseBean[].class); }else { throw makeNoSuchMethodException(def); } } return new MethodInvoker(def, impl, delegate, pkType); } //_____________________________________________________________________ // // SELF-REFERENCE //_____________________________________________________________________ private MethodInvoker listOfSelfRef(Method def) throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 1,"only 1 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(P_LISTOFSELFREF); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_LISTOFSELFREF); String readableName = matcher.group(1); ForeignKeyMetaData selfRefKey = metaData.getSelfRefKeyByRn(readableName); Method impl = getDeclaredMethod(D_LISTOFSELFREF, paramBuilder().add(selfRefKey.name.getClass(),paramTypes).genericNormalize(1, Object[].class).build()); return new MethodInvoker(def, impl, delegate, selfRefKey.name); } private MethodInvoker levelOfSelfRef(Method def) throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 1,"only 1 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(P_LEVELOFSELFREF); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_LEVELOFSELFREF); String readableName = matcher.group(1); ForeignKeyMetaData selfRefKey = metaData.getSelfRefKeyByRn(readableName); Method impl = getDeclaredMethod(D_LEVELOFSELFREF, paramBuilder().add(selfRefKey.name.getClass(),paramTypes).genericNormalize(1, Object[].class).build()); return new MethodInvoker(def, impl, delegate, selfRefKey.name); } private MethodInvoker isCycleOfSelfRef(Method def) throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 1,"only 1 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(P_ISCYCLEOFSELFREF); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_ISCYCLEOFSELFREF); String readableName = matcher.group(1); ForeignKeyMetaData selfRefKey = metaData.getSelfRefKeyByRn(readableName); Method impl = getDeclaredMethod(D_ISCYCLEOFSELFREF, paramBuilder().add(selfRefKey.name.getClass(),paramTypes).genericNormalize(1, Object[].class).build()); return new MethodInvoker(def, impl, delegate, selfRefKey.name); } private MethodInvoker checkCycleOfSelfRef(Method def) throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 1,"only 1 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(P_CHECKCYCLEOFSELFREF); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_CHECKCYCLEOFSELFREF); String readableName = matcher.group(1); ForeignKeyMetaData selfRefKey = metaData.getSelfRefKeyByRn(readableName); Method impl = getDeclaredMethod(D_CHECKCYCLEOFSELFREF, paramBuilder().add(selfRefKey.name.getClass(),paramTypes).genericNormalize(1, Object.class).build()); return new MethodInvoker(def, impl, delegate, selfRefKey.name); } private MethodInvoker topOfSelfRef(Method def) throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 1,"only 1 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(P_TOPOFSELFREF); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",P_TOPOFSELFREF); String readableName = matcher.group(1); ForeignKeyMetaData selfRefKey = metaData.getSelfRefKeyByRn(readableName); Method impl = getDeclaredMethod(D_TOPOFSELFREF, paramBuilder().add(selfRefKey.name.getClass(),paramTypes).genericNormalize(1, Object[].class).build()); return new MethodInvoker(def, impl, delegate, selfRefKey.name); } private MethodInvoker childListOfSelfRef(Method def) throws NoSuchMethodException, SecurityException{ return methodOfRecursionOfSelfRef(def,P_CHILDLISTOFSELFREF,D_CHILDLISTOFSELFREF, Object[].class); } private MethodInvoker childrenOfSelfRef(Method def) throws NoSuchMethodException, SecurityException{ return methodOfRecursionOfSelfRef(def,P_CHILDRENOFSELFREF,D_CHILDRENOFSELFREF, Object[].class); } private MethodInvoker childrenOfSelfRefForBeans(Method def) throws NoSuchMethodException, SecurityException{ return methodOfRecursionOfSelfRef(def,P_CHILDRENOFBEANSOFSELFREF,D_CHILDRENOFBEANSOFSELFREF, null); } private MethodInvoker childrenOfSelfRefForPks(Method def) throws NoSuchMethodException, SecurityException{ return methodOfRecursionOfSelfRef(def,P_CHILDRENOFPKSOFSELFREF,D_CHILDRENOFPKSOFSELFREF, null); } private MethodInvoker methodOfRecursionOfSelfRef(Method def,String regex,String delegateName, Class normalizeFirstArgType) throws NoSuchMethodException, SecurityException{ Class[] paramTypes = def.getParameterTypes(); String methodName = def.getName(); checkArgument(paramTypes.length == 1,"only 1 parameter required for %s",def.getName()); Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(methodName); checkArgument(matcher.matches(),"INVALID method name pattern,%s required",regex); String readableName = matcher.group(1); ForeignKeyMetaData selfRefKey = metaData.getSelfRefKeyByRn(readableName); Method impl = getDeclaredMethod(delegateName, paramBuilder().add(selfRefKey.name.getClass(),paramTypes).genericNormalize(1, normalizeFirstArgType).build()); return new MethodInvoker(def, impl, delegate, selfRefKey.name); } private static final boolean isVoid(Class clazz){ return "void".equals(clazz.getName()); } private static final Class wrapBaseBean(Class type){ if(null != type){ if(type.isArray()){ Class componentType = wrapBaseBean(type.getComponentType()); if(componentType != type.getComponentType()){ return Array.newInstance(componentType, 0).getClass(); } return type; }else{ if(BaseBean.class.isAssignableFrom(type)){ return BaseBean.class; } return type; } } return type; } private static final Class[] wrapBaseBean(Class... types){ if(null != types){ for(int i=0;i> builder = Lists.newLinkedList(); ParamTypeBuilder add(Classtype){ builder.add(type); return this; } ParamTypeBuilder add(Class[]types,int start){ builder.addAll(Arrays.asList(Arrays.copyOfRange(types, start, types.length))); return this; } ParamTypeBuilder add(Class type,Class ...types){ builder.add(type); builder.addAll(Arrays.asList(types)); return this; } /** * 对象索引指定的类型进行泛型归一化
* 如果为{@link BaseBean}的子类则改为{@link BaseBean},否则改为{@code normalClass} * @param index * @param normalizeClass 归一化类型 * @return 当前对象 */ ParamTypeBuilder genericNormalize(int index,Class normalizeClass){ try { Class type = builder.get(index); if(BaseBean.class.isAssignableFrom(type)){ builder.set(index, BaseBean.class); }else if(null != normalizeClass){ builder.set(index, normalizeClass); } } catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException(logString("INVALID index %s for parameter types array", index)); } return this; } /** * 对象索引指定的类型进行泛型归一化
* 如果为{@link BaseBean}的子类则改为{@link BaseBean},否则改为{@code normalClass}, * 删除{@code index}之后的所有元素 * @param index * @param normalizeClass 归一化类型 * @return 当前对象 */ ParamTypeBuilder normalizeLast(int index,Class normalizeClass){ try { Class type = builder.get(index); if(BaseBean.class.isAssignableFrom(type)){ builder.set(index, BaseBean.class); }else{ builder.set(index, normalizeClass); } // 删除index之后续的所有元素 while(builder.size() > index+1){ builder.remove(index + 1); } } catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException(logString("INVALID index %s for parameter types array", index)); } return this; } Class[] build(){ return builder.toArray(new Class[0]); } } private static ParamTypeBuilder paramBuilder(){ return new ParamTypeBuilder(); } /** * 调用执行方法调用,剥离封装在{@link InvocationTargetException}中的方法调用异常直接抛出 * @param method 方法对象(不可为{@code null}) * @param obj 方法调用对象 * @param input 方法调用参数 * @return 方法调用返回值 * @throws Throwable */ private static Object stripedInvoke(Method method,Object obj,Object... input) throws Throwable { try { return method.invoke(obj, input); } catch (InvocationTargetException e) { Throwable te = e.getTargetException(); if(te != null){ // if(debug){ //// log("InvocationTargetException:"+te.toString(), te); // log("InvocationTargetException:"+te.toString()); // } /** 剥离出方法调用中产生的异常直接抛出 */ throw te; }else{ log(e.toString()); throw e; } } } /** * 方法调用接口 * @author guyadong */ interface Invoker { static final Object[] EMPTY_OBJECT_ARRAY = new Object[]{}; /** * 执行方法调用 * @param input 输入参数数组 * @return 调用返回值 * @throws Throwable 方法调用抛出异常 */ Object invoke(Object[] input) throws Throwable; } private class ObjectInvoker implements Invoker{ final Method method; ObjectInvoker(Method method) { this.method = method; } @Override public Object invoke(Object[] input) throws Throwable { return stripedInvoke(method, delegate, firstNonNull(input,EMPTY_OBJECT_ARRAY)); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("\n"); builder.append(" @Override\n"); builder.append(" public ").append(signatureOf(method,true,true)).append("{\n"); builder.append(" "); if(!isVoid(method.getReturnType())){ builder.append("return "); } builder.append("delegate.").append(method.getName()).append("("); Class[] paramTypes = method.getParameterTypes(); for(int j = 0; j < paramTypes.length;++j){ if(j > 0){ builder.append(","); } builder.append("arg").append(j); } builder.append(");\n"); builder.append(" }\n"); return builder.toString(); } } /** * 方法调用对象,用于封装执行方法调用时的所有信息 * @author guyadong * */ private class MethodInvoker implements Invoker { /** 接口方法 */ final Method def; /** {@link #manager}中与接口方法({@link #def})对应的实现方法 */ final Method impl; /** 执行方法调用的对象 */ protected final BaseTableManager manager; /** 执行方法调用时除原有传入参数之外的附加参数列表(排在原输入参数之前) */ protected final Object[] additionalParams; /** 调用参数转换器,用于生成调用方法({@link #impl})的参数 */ private final Function argsMaker; /** * @param def 接口方法 * @param impl 实现方法 * @param manager 执行调用的对象 * @param additionalParams 附加参数列表 */ private MethodInvoker(Method def, Method impl,BaseTableManager manager, Object... additionalParams) { this.def = def; this.impl = impl; if(!Modifier.isPublic(impl.getModifiers())){ /** 非public方法必须设置为可访问 */ impl.setAccessible(true); } this.manager = checkNotNull(manager,"manager is null"); this.additionalParams = firstNonNull(additionalParams, EMPTY_OBJECT_ARRAY); Class[] paramTypes = impl.getParameterTypes(); if(paramTypes.length == additionalParams.length + 1 && Object[].class.equals(paramTypes[additionalParams.length])){ argsMaker = vaArgsMaker; }else if(additionalParams.length == 0){ argsMaker = defaultArgsMaker; }else { argsMaker = addparamArgsMaker; } } /** 默认参数转换器,不对输入参数做任何修改原样返回 */ private final Function defaultArgsMaker = new Function() { @Override public Object[] apply(Object[] input) { return input; } }; /** 有附加参数的参数转换器,创建新的Object数组,将附加参数,原输入参数顺序复制到新数组返回 */ private final Function addparamArgsMaker = new Function() { @Override public Object[] apply(Object[] input) { Object[] args = new Object[additionalParams.length + input.length]; System.arraycopy(additionalParams, 0, args, 0, additionalParams.length); System.arraycopy(input, 0, args, additionalParams.length, input.length); return args; } }; /** * 输入参数为变长参数数组的参数转换器, 创建新的Object数组, * 将附加参数复制到新数组,并将输入参数数组做为一个整体添加到新数组最后返回 */ private final Function vaArgsMaker = new Function() { @Override public Object[] apply(Object[] input){ Class[] paramTypes = impl.getParameterTypes(); Object[] args = new Object[paramTypes.length]; System.arraycopy(additionalParams, 0, args, 0, additionalParams.length); if(input[0] instanceof Object[]){ args[additionalParams.length] = input[0]; }else{ args[additionalParams.length] = input; } return args; } }; @Override public Object invoke(Object[] input) throws Throwable { return stripedInvoke(impl, manager, argsMaker.apply(firstNonNull(input, EMPTY_OBJECT_ARRAY))); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("\n"); builder.append(" @Override\n"); builder.append(" public ").append(signatureOf(def,true,true)).append("{\n"); builder.append(" "); if(!isVoid(def.getReturnType())){ builder.append("return "); } builder.append(manager == delegate? "delegate.": BaseTableManager.class.getName()+".instanceOf(" + manager.getClass().getName() + ".class)."); builder.append(impl.getName()); builder.append("("); int i=0; for(; i < additionalParams.length;++i){ if(i>0){ builder.append(","); } if(additionalParams[i] instanceof String){ builder.append("\"" + additionalParams[i] + "\""); } else if(additionalParams[i] instanceof Class){ builder.append(((Class)additionalParams[i]).getName() + ".class"); }else { builder.append(additionalParams[i]); } } Class[] paramTypes = def.getParameterTypes(); for(int j = 0; j < paramTypes.length; ++j){ if(i++ > 0){ builder.append(","); } builder.append("arg").append(j); } builder.append(");\n"); builder.append(" }\n"); return builder.toString(); } } private class SaveFullyInvoker extends MethodInvoker{ /** * @param def 接口方法 * @param impl 实现方法 */ private SaveFullyInvoker(Method def, Method impl) { super(def, impl, delegate); } @Override public Object invoke(Object[] input) throws Throwable { return stripedInvoke(impl, manager, input[0],Arrays.copyOfRange(input, 1, input.length)); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("\n"); builder.append(" @Override\n"); builder.append(" public ").append(signatureOf(def,true,true)).append("{\n"); builder.append(" ").append("return ").append("delegate.").append(impl.getName()).append("("); Class[] paramTypes = def.getParameterTypes(); builder.append("arg0,new Object[]{"); for(int j = 0; j < paramTypes.length; ++j){ if(j>0){ builder.append(", "); } builder.append("arg").append(j); } builder.append("});\n"); builder.append(" }\n"); return builder.toString(); } } }