001/* 002 * JKNIV, whinstone one contract to access your database. 003 * 004 * Copyright (C) 2017, the original author or authors. 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software Foundation, Inc., 018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 019 */ 020package net.sf.jkniv.whinstone.commands; 021 022import java.lang.reflect.Method; 023import java.sql.Statement; 024import java.util.HashMap; 025import java.util.Map; 026import java.util.Set; 027 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031import net.sf.jkniv.asserts.Assertable; 032import net.sf.jkniv.asserts.AssertsFactory; 033import net.sf.jkniv.exception.HandleableException; 034import net.sf.jkniv.reflect.beans.ObjectProxy; 035import net.sf.jkniv.reflect.beans.ObjectProxyFactory; 036import net.sf.jkniv.sqlegance.Sql; 037import net.sf.jkniv.sqlegance.SqlType; 038import net.sf.jkniv.sqlegance.dialect.SqlFeatureSupport; 039import net.sf.jkniv.whinstone.Queryable; 040import net.sf.jkniv.whinstone.ResultRow; 041 042/** 043 * 044 * @author Alisson Gomes 045 * @since 0.6.0 046 */ 047public abstract class DefaultCommandHandler implements CommandHandler 048{ 049 final static Logger LOG = LoggerFactory 050 .getLogger(DefaultCommandHandler.class); 051 static final Assertable NOT_NULL = AssertsFactory.getNotNull(); 052 private final static Map<String, ObjectCallback> OBJECTS_CALLBACKS = new HashMap<String, ObjectCallback>(); 053 CommandAdapter cmdAdapter; 054 Command command; 055 ObjectProxy<?> proxyParams; 056 protected Queryable queryable; 057 protected Sql sql; 058 //protected RepositoryConfig config; 059 protected ResultRow<?, ?> overloadResultRow; 060 protected HandleableException handleableException; 061 062 public DefaultCommandHandler(CommandAdapter cmdAdapter) 063 { 064 this.cmdAdapter = cmdAdapter; 065 } 066 067 @Override 068 public CommandHandler with(ResultRow<?, ?> overloadResultRow) 069 { 070 this.overloadResultRow = overloadResultRow; 071 return this; 072 } 073 074 @Override 075 public CommandHandler with(Queryable queryable) 076 { 077 this.queryable = queryable; 078 if (queryable.getParams() != null) 079 { 080 this.proxyParams = ObjectProxyFactory.of(queryable.getParams()); 081 CallbackProcessor processor = new CallbackProcessor(this.proxyParams); 082 if (!OBJECTS_CALLBACKS.containsKey(proxyParams.getTargetClass().getName())) 083 { 084 ObjectCallback objectCallback = processor.loadCallbackEvents(); 085 OBJECTS_CALLBACKS.put(proxyParams.getTargetClass().getName(), objectCallback); 086 } 087 } 088 //loadCallbackEvents(); 089 return this; 090 } 091 092 @Override 093 public CommandHandler with(Sql sql) 094 { 095 this.sql = sql; 096 return this; 097 } 098 099 public CommandHandler with(HandleableException handlerException) 100 { 101 this.handleableException = handlerException; 102 return this; 103 } 104 105 @Override 106 public <T> T run() 107 { 108 NOT_NULL.verify(this.cmdAdapter, this.queryable, this.sql); 109 T t = null; 110 Number rows = 0; 111 if (LOG.isTraceEnabled()) 112 LOG.trace("Executing [{}] as {} command", queryable, sql.getSqlType()); 113 try 114 { 115 // JPA with a entity doesn't assert validate 116 // how can fix/improve this? 117 if(!queryable.isBoundSql()) 118 queryable.bind(sql); 119 try 120 { 121 preCallback(); 122 sql.getValidateType().assertValidate(queryable.getParams()); 123 this.command = asCommand(); 124 t = this.command.execute(); 125 if (t instanceof Number) 126 rows = (Number) t; 127 if (queryable.getDynamicSql().getSqlDialect().supportsFeature(SqlFeatureSupport.PAGING_ROUNDTRIP)) 128 queryable.setTotal(rows.longValue()); 129 else 130 queryable.setTotal(Statement.SUCCESS_NO_INFO); 131 if (LOG.isDebugEnabled()) 132 LOG.debug("{} records was affected by {} [{}] query", rows, sql.getSqlType(), queryable.getName()); 133 postCallback(); 134 } 135 catch (Exception e) 136 { 137 queryable.setTotal(Statement.EXECUTE_FAILED); 138 postException(); 139 handleableException.handle(e); 140 } 141 } 142 finally 143 { 144 this.cmdAdapter.close(); 145 } 146 return t; 147 } 148 149 protected CommandAdapter getCommandAdapter() 150 { 151 return this.cmdAdapter; 152 } 153 154 @Override 155 public CommandHandler preCallback() 156 { 157 if (proxyParams != null) 158 { 159 ObjectCallback objectCallback = OBJECTS_CALLBACKS.get(proxyParams.getTargetClass().getName()); 160 if (objectCallback != null) 161 { 162 Set<Method> methods = objectCallback.getPreMethods(sql.getSqlType()); 163 for (Method m : methods) 164 proxyParams.invoke(m); 165 } 166 } 167 return this; 168 } 169 170 @Override 171 public CommandHandler postCallback() 172 { 173 if (proxyParams != null) 174 { 175 ObjectCallback objectCallback = OBJECTS_CALLBACKS.get(proxyParams.getTargetClass().getName()); 176 if (objectCallback != null) 177 { 178 Set<Method> methods = objectCallback.getPostMethods(sql.getSqlType()); 179 for (Method m : methods) 180 proxyParams.invoke(m); 181 } 182 } 183 return this; 184 } 185 186 @Override 187 public CommandHandler postCommit()// TODO Callback implmements POST_COMMIT 188 { 189 // if (proxyParams != null) 190 // { 191 // CallbackMethods preCallbackMethods = CacheCallback.get(proxyParams.getTargetClass(), sql.getSqlType()); 192 // for (Method m : preCallbackMethods.getCallbacks()) 193 // proxyParams.invoke(m); 194 // } 195 return this; 196 } 197 198 @Override 199 public CommandHandler postException()// TODO Callback implmements POST_EXCEPTION 200 { 201 // if (proxyParams != null) 202 // { 203 // CallbackMethods preCallbackMethods = CacheCallback.get(proxyParams.getTargetClass(), sql.getSqlType()); 204 // for (Method m : preCallbackMethods.getCallbacks()) 205 // proxyParams.invoke(m); 206 // } 207 return this; 208 } 209 210 211 @Override 212 public CommandHandler checkSqlType(SqlType expected) 213 { 214 if (sql == null) 215 throw new IllegalArgumentException("Null Sql reference wasn't expected"); 216 217 if (sql.getSqlType() != expected) 218 throw new IllegalArgumentException("Cannot execute sql [" + sql.getName() + "] as " + sql.getSqlType() 219 + ", " + expected + " was expect"); 220 221 return this; 222 } 223 224}