001package gu.sql2java; 002 003import static com.google.common.base.Preconditions.checkArgument; 004import static com.google.common.base.Preconditions.checkNotNull; 005import static gu.sql2java.SimpleLog.log; 006import static gu.sql2java.SimpleLog.logString; 007 008import java.lang.reflect.InvocationHandler; 009import java.lang.reflect.Proxy; 010import java.util.Collections; 011import java.util.EnumMap; 012import java.util.Map; 013import java.util.Map.Entry; 014import java.util.NoSuchElementException; 015import java.util.concurrent.TimeUnit; 016 017import com.google.common.base.Function; 018import com.google.common.base.Predicate; 019import com.google.common.collect.ImmutableMap; 020import com.google.common.collect.Iterables; 021import com.google.common.collect.Maps; 022import gu.sql2java.Constant.JdbcProperty; 023import gu.sql2java.Constant.UpdateStrategy; 024 025/** 026 * 数据库操作实例({@link TableManager})管理类 027 * @author guyadong 028 * 029 */ 030public class Managers { 031 /** 032 * 设置是否输出调试信息标志 033 */ 034 private static boolean debug = false; 035 private Managers() { 036 } 037 038 private static final ImmutableMap<String, TableManager<? extends BaseBean>> 039 tableManagerInstances = loadTableManager(); 040 private static final ImmutableMap<Class<?>, TableManager<? extends BaseBean>> 041 tableManagerTypeMaps = asTypeMap(tableManagerInstances); 042 private static final ImmutableMap<Class<?>, TableManager<? extends BaseBean>> 043 tableManagerBeanTypeMaps = asBeanTypeMap(tableManagerInstances); 044 private static final Map<Class<?>, TableManager<? extends BaseBean>> cacheManagers = Maps.newHashMap(); 045 private static final Map<Class<?>, TableManager<? extends BaseBean>> cacheBeanTypeManagers = Maps.newHashMap(); 046 private static final Map<String, TableManager<? extends BaseBean>> cacheNameManagers = Maps.newHashMap(); 047 048 /** 049 * @return 返回所有数据库操作实例(非cache) 050 */ 051 public static ImmutableMap<String, TableManager<? extends BaseBean>> getTableManagers() { 052 return tableManagerInstances; 053 } 054 055 /** 056 * SPI(Service Provider Interface)机制加载 {@link TableManager}所有实例 057 * @return 表名和 {@link TableManager}实例的映射对象 058 */ 059 private static ImmutableMap<String, TableManager<? extends BaseBean>> loadTableManager() { 060 ImmutableMap.Builder<String, TableManager<? extends BaseBean>> builder = ImmutableMap.builder(); 061 for(RowMetaData data:RowMetaData.tableMetadata.values()){ 062 TableManager<?> manager = TableManagerDecorator.makeInterfaceInstance(new BaseTableManager<>(data.tablename)); 063 builder.put(data.tablename, manager); 064 if(debug){ 065 log("TableManagerDecorator instance create for {} ",data.tablename); 066 } 067 } 068 return builder.build(); 069 } 070 071 private static final ImmutableMap<Class<?>, TableManager<? extends BaseBean>> asTypeMap(Map<String, TableManager<? extends BaseBean>>input){ 072 return Maps.uniqueIndex(input.values(), new Function<TableManager<? extends BaseBean>,Class<?>>(){ 073 @Override 074 public Class<?> apply(TableManager<? extends BaseBean> input) { 075 for(Class<?> clazz:input.getClass().getInterfaces()){ 076 for(Class<?> c:clazz.getInterfaces()){ 077 if(c.equals(TableManager.class)){ 078 return clazz; 079 } 080 } 081 } 082 throw new IllegalStateException(logString("NOT FOUND immplements interface class for %s ", input.getClass())); 083 }}); 084 } 085 086 private static final ImmutableMap<Class<?>, TableManager<? extends BaseBean>> asBeanTypeMap(Map<String, TableManager<? extends BaseBean>>input){ 087 return Maps.uniqueIndex(input.values(), new Function<TableManager<? extends BaseBean>,Class<?>>(){ 088 089 @Override 090 public Class<?> apply(TableManager<? extends BaseBean> input) { 091 if(input instanceof BaseTableManager){ 092 return ((BaseTableManager<?>)input).metaData.beanType; 093 }else if(Proxy.isProxyClass(input.getClass())){ 094 InvocationHandler handler = Proxy.getInvocationHandler(input); 095 checkArgument(handler instanceof TableManagerDecorator,"UNKNOW HANDLER %s",handler.getClass() ); 096 return ((TableManagerDecorator<?>)handler).metaData.beanType; 097 } 098 throw new IllegalArgumentException(logString("UNKNOW SUPPORTED TableManager instance %s",input.getClass())); 099 }}); 100 } 101 102 /** 103 * 根据表操作接口类型返回数据库操作实例(非cache) 104 * @param interfaceClass 接口类型 105 * @return {@link TableManager}实例,找不到则抛出异常 106 */ 107 @SuppressWarnings("unchecked") 108 public static final <M extends TableManager<?>>M 109 getTableManager(Class<M>interfaceClass) { 110 TableManager<? extends BaseBean> manager = tableManagerTypeMaps.get(interfaceClass); 111 return checkNotNull((M) manager,"INVALID manager type %s",interfaceClass); 112 } 113 114 /** 115 * 根据表记录类型返回数据库操作实例(非cache) 116 * @param beanType java bean type 117 * @return {@link TableManager}实例,找不到则抛出异常 118 */ 119 @SuppressWarnings("unchecked") 120 public static final <T extends BaseBean,M extends TableManager<T>>M 121 getTableManagerByBeanType(Class<T>beanType) { 122 TableManager<? extends BaseBean> manager = tableManagerBeanTypeMaps.get(beanType); 123 return checkNotNull((M) manager,"INVALID bean type %s",beanType); 124 } 125 126 /** 127 * 根据表名返回数据库操作实例(非cache) 128 * @param tablename table name 129 * @return {@link TableManager}实例,找不到则抛出异常 130 */ 131 @SuppressWarnings("unchecked") 132 public static final <M extends TableManager<?>>M 133 getTableManager(String tablename) { 134 TableManager<? extends BaseBean> manager = tableManagerInstances.get(tablename); 135 return checkNotNull((M) manager,"INVALID tablename %s",tablename); 136 } 137 138 /** 139 * 根据表名返回数据库操作实例(非cache) 140 * @param tablename table name 141 * @return {@link BaseTableManager}实例,找不到则抛出异常 142 */ 143 @SuppressWarnings("unchecked") 144 public static final <M extends BaseTableManager<?>>M 145 getBaseTableManager(String tablename) { 146 return (M) baseManagerOf(getTableManager(tablename)); 147 } 148 149 /** 150 * 注册cache manager<br> 151 * @param tablename table name 152 * @param updateStrategy cache update strategy,{@link Constant#DEFAULT_STRATEGY} be used if {@code null} 153 * @param maximumSize maximum capacity of cache ,{@link Constant#DEFAULT_CACHE_MAXIMUMSIZE } be used if {@code null} or <=0,see also {@link CacheBuilder#maximumSize(long)} 154 * @param duration cache data expired time,{@link Constant#DEFAULT_DURATION} be used if {@code null} or <=0,see also {@link CacheBuilder#expireAfterWrite(long, TimeUnit)} 155 * @param unit time unit for {@code duration},{@link Constant#DEFAULT_TIME_UNIT} be used if {@code null},see also {@link CacheBuilder#expireAfterWrite(long, TimeUnit)} 156 */ 157 public static synchronized final <I extends TableManager<?>> 158 void registerCacheManager( 159 String tablename, 160 UpdateStrategy updateStrategy, 161 long maximumSize, 162 long duration, 163 TimeUnit unit){ 164 TableManager<?> cacheManager = CacheManager.makeCacheInstance(tablename, updateStrategy, maximumSize, duration, unit); 165 BaseTableManager<?> manager = baseManagerOf(cacheManager); 166 cacheManagers.put(manager.metaData.managerInterfaceClass, cacheManager); 167 cacheNameManagers.put(manager.metaData.tablename, cacheManager); 168 cacheBeanTypeManagers.put(manager.metaData.beanType, cacheManager); 169 if(debug){ 170 log("REGISTER CACHE MANAGER {}",cacheManager); 171 } 172 } 173 174 /** 175 * @return 返回所有支持缓存的数据库操作实例 176 * @see CacheManager 177 */ 178 public static Map<Class<?>, TableManager<? extends BaseBean>> getCacheManagers() { 179 return Collections.unmodifiableMap(cacheManagers); 180 } 181 182 /** 183 * 根据目标类型返回对应的支持缓存的 {@link TableManager}实例 184 * @param interfaceClass 目标接口类型 185 * @return {@link TableManager}实例 186 * @throws NoSuchElementException 找不到时抛出异常 187 */ 188 @SuppressWarnings("unchecked") 189 public static final <M extends TableManager<? extends BaseBean>>M 190 getCacheManager(final Class<M>interfaceClass) throws NoSuchElementException { 191 checkArgument(interfaceClass != null,"targetType is null"); 192 TableManager<? extends BaseBean> manager; 193 if(null != (manager = cacheManagers.get(interfaceClass))){ 194 return (M) manager; 195 } 196 return (M) Iterables.find(cacheManagers.values(), new Predicate<TableManager<?>>() { 197 198 @Override 199 public boolean apply(TableManager<?> input) { 200 return interfaceClass.isInstance(input); 201 } 202 }); 203 } 204 205 /** 206 * 根据表记录类型返回支持缓存的数据库操作实例 207 * @param beanType java bean type 208 * @return {@link TableManager}实例,找不到时抛出异常 209 */ 210 @SuppressWarnings("unchecked") 211 public static final <B extends BaseBean> TableManager<B> 212 getCacheManagerByBeanType(Class<?> beanType) { 213 TableManager<? extends BaseBean> manager = cacheBeanTypeManagers.get(beanType); 214 return ( TableManager<B>) checkNotNull(manager,"INVALID bean type %s",beanType); 215 } 216 217 /** 218 * 根据表名返回支持缓存的数据库操作实例 219 * @param tablename 220 * @return {@link TableManager}实例,找不到时抛出异常 221 */ 222 @SuppressWarnings("unchecked") 223 public static final <B extends BaseBean> TableManager<B> 224 getCacheManager(String tablename) { 225 TableManager<? extends BaseBean> manager = cacheNameManagers.get(tablename); 226 return (TableManager<B>) checkNotNull(manager,"INVALID table name %s",tablename); 227 } 228 229 /** 230 * 根据表记录类型返回数据库操作实例<br> 231 * 优先返回支持缓存的数据库操作实例(cache) 232 * @param interfaceClass 接口类 233 * @return {@link TableManager}实例,找不到时抛出异常 234 */ 235 public static <M extends TableManager<? extends BaseBean>>M 236 instanceOf(Class<M>interfaceClass) { 237 try { 238 return getCacheManager(interfaceClass); 239 } catch (Exception e) { 240 return getTableManager(interfaceClass); 241 } 242 } 243 244 /** 245 * 根据表名返回数据库操作实例<br> 246 * 优先返回支持缓存的数据库操作实例(cache) 247 * @param tablename table name 248 * @return {@link TableManager}实例,找不到时抛出异常 249 */ 250 public static <B extends BaseBean>TableManager<B> managerOf(String tablename) { 251 try { 252 return getCacheManager(tablename); 253 } catch (Exception e) { 254 return getTableManager(tablename); 255 } 256 } 257 258 /** 259 * 将数据库操作实例转换对应的{@link BaseTableManager}实例<br> 260 * @param manager 261 * @return {@link BaseTableManager}实例,转换失败时抛出异常 262 */ 263 @SuppressWarnings({ "unchecked", "rawtypes" }) 264 static <B extends BaseBean>BaseTableManager<B> baseManagerOf(TableManager<B> manager){ 265 checkArgument(manager != null,"manager is null"); 266 if(manager instanceof BaseTableManager){ 267 return (BaseTableManager<B>) manager; 268 }else if(Proxy.isProxyClass(manager.getClass())){ 269 InvocationHandler handler = Proxy.getInvocationHandler(manager); 270 checkArgument(handler instanceof TableManagerDecorator,"UNKNOW HANDLER TYPE %s",manager.getClass()); 271 return ((TableManagerDecorator)handler).delegate; 272 }else { 273 throw new IllegalArgumentException(logString("UNKNOW TableManager instance type %s",manager.getClass())); 274 } 275 } 276 277 /** 278 * 根据表名返回对应的{@link BaseTableManager}实例 279 * 优先返回支持缓存的数据库操作实例(cache) 280 * @param tablename table name 281 * @return {@link BaseTableManager}实例,找不到时抛出异常 282 */ 283 @SuppressWarnings("unchecked") 284 static <B extends BaseBean>BaseTableManager<B> baseManagerOf(String tablename) { 285 return baseManagerOf((TableManager<B>)managerOf(tablename)); 286 } 287 288 /** 289 * 根据数据表名(驼峰命名格式)返回对应的{@link TableManager}实例<br> 290 * 优先返回支持缓存的数据库操作实例(cache) 291 * @param coreClass 292 * @return {@link TableManager}实例,找不到时抛出异常 293 */ 294 public static <B extends BaseBean>TableManager<B> managerOfCoreClass(String coreClass) { 295 String tablename = RowMetaData.getRowMetaDataByCoreClassName(coreClass).tablename; 296 try { 297 return getCacheManager(tablename); 298 } catch (Exception e) { 299 return getTableManager(tablename); 300 } 301 } 302 303 /** 304 * 根据表记录类型返回数据库操作实例(非cache)<br> 305 * 优先返回支持缓存的数据库操作实例 306 * @param beanType java bean type 307 * @return {@link TableManager}实例,找不到时抛出异常 308 */ 309 public static <B extends BaseBean>TableManager<B> managerOf(Class<B> beanType) { 310 try { 311 return getCacheManagerByBeanType(beanType); 312 } catch (Exception e) { 313 return getTableManagerByBeanType(beanType); 314 } 315 } 316 public enum Module{ 317 MANAGER,CACHE,DECORATOR,MANAGERS,BASETABLEMANAGER 318 } 319 /** 320 * set debug flag that determine if output log message,default : false 321 * @param debug flag for debug message output 322 * @param modules modules array to be set debug flag,all modules used if be null or empty 323 */ 324 public static void setDebug(boolean debug,Module... modules){ 325 if(modules == null || modules.length == 0){ 326 modules = Module.values(); 327 } 328 for(Module module:modules){ 329 if(null != module){ 330 switch (module) { 331 case MANAGER: 332 Manager.getInstance().setDebug(debug); 333 break; 334 case CACHE: 335 ColumnCache.setDebug(debug); 336 break; 337 case DECORATOR: 338 TableManagerDecorator.setDebug(debug); 339 break; 340 case MANAGERS: 341 Managers.debug = debug; 342 break; 343 case BASETABLEMANAGER: 344 BaseTableManager.setDebug(debug); 345 break; 346 default: 347 break; 348 } 349 } 350 } 351 } 352 353 /** 354 * inject properties to {@link Manager#databaseProperties}<br> 355 * be effected only while called before initializing singleton instance 356 * @param properties 357 * @see JdbcProperty 358 */ 359 public static final void injectProperties(Map<String,String> properties){ 360 if(null != properties){ 361 EnumMap<JdbcProperty, String> enumMap = new EnumMap<JdbcProperty,String>(JdbcProperty.class); 362 JdbcProperty property; 363 for(Entry<String, String> entry:properties.entrySet()){ 364 if(null != (property = JdbcProperty.fromKey(entry.getKey()))){ 365 enumMap.put(property, entry.getValue()); 366 } 367 } 368 Manager.injectProperties(enumMap); 369 } 370 } 371 372 /** 373 * @return singleton instance of {@link Manager} as {@link SqlRunner} instance 374 */ 375 public static SqlRunner getSqlRunner(){ 376 return Manager.getInstance(); 377 } 378}