/*
* Copyright 2009-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.plugin;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.io.ResolverUtil;
import org.apache.ibatis.jdbc.SqlRunner;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.session.Configuration;
import com.lanyuan.plugin.PagePlugin;
import com.lanyuan.plugin.PageView;
import com.lanyuan.util.Common;
/**
* @author Clinton Begin
*/
public class Plugin implements InvocationHandler {
private Object target;
private Interceptor interceptor;
private Map<Class<?>, Set<Method>> signatureMap;
private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
this.target = target;
this.interceptor = interceptor;
this.signatureMap = signatureMap;
}
public static Object wrap(Object target, Interceptor interceptor) {
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
if (interfaces.length > 0) {
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));
}
return target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Set<Method> methods = signatureMap.get(method.getDeclaringClass());
if (methods != null && methods.contains(method)) {
return interceptor.intercept(new Invocation(target, method, args));
}
return method.invoke(target, args);
} catch (Exception e) {
throw ExceptionUtil.unwrapThrowable(e);
}
}
private static Map<Class<?>, Set<Method>> getSignatureMap(Interceptor interceptor) {
Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);
if (interceptsAnnotation == null) { // issue #251
throw new PluginException("No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName());
}
Signature[] sigs = interceptsAnnotation.value();
Map<Class<?>, Set<Method>> signatureMap = new HashMap<Class<?>, Set<Method>>();
for (Signature sig : sigs) {
Set<Method> methods = signatureMap.get(sig.type());
if (methods == null) {
methods = new HashSet<Method>();
signatureMap.put(sig.type(), methods);
}
try {
Method method = sig.type().getMethod(sig.method(), sig.args());
methods.add(method);
} catch (NoSuchMethodException e) {
throw new PluginException("Could not find method on " + sig.type() + " named " + sig.method() + ". Cause: " + e, e);
}
}
return signatureMap;
}
private static Class<?>[] getAllInterfaces(Class<?> type, Map<Class<?>, Set<Method>> signatureMap) {
Set<Class<?>> interfaces = new HashSet<Class<?>>();
while (type != null) {
for (Class<?> c : type.getInterfaces()) {
if (signatureMap.containsKey(c)) {
interfaces.add(c);
}
}
type = type.getSuperclass();
}
return interfaces.toArray(new Class<?>[interfaces.size()]);
}
public static final String joinSql( Connection connection, MappedStatement mappedStatement, BoundSql boundSql, Map<String, Object> formMap, List<Object> formMaps)throws Exception{
Object table = null;
String sql = "";
if(null!=formMap){
table = formMap.get(Configuration.LY_TABLE);
sql=" SELECT * FROM "+table.toString().toUpperCase();
}
String sqlId = mappedStatement.getId();
sqlId = sqlId.substring(sqlId.lastIndexOf(".")+1);
if(Configuration.FINDBYWHERE.equals(sqlId)){
if(null!=formMap.get("where")&&!StringUtils.isBlank(formMap.get("where").toString())){
sql +=" "+formMap.get("where").toString();
}
}else if(Configuration.FINDBYPAGE.equals(sqlId)){
Map<String, Object> mapfield = SqlRunner.findByTablefield(connection, boundSql, table.toString());
String field = mapfield.get(Configuration.FIELD).toString();
String[] fe = field.split(",");
String param = "";
for (String string : fe) {
if(formMap.containsKey(string)){
Object v =formMap.get(string);
if(v.toString().indexOf("%")>-1)
{
param += " AND "+string+" like '"+v+"'";
}else{
if(ResolverUtil.isNumeric1(v.toString())){
param += " AND "+string+" = "+v;
}else{
param += " AND "+string+" = '"+v+"'";
}
}
}
}
if(StringUtils.isNotBlank(param)){
param=param.substring(param.indexOf("AND")+4);
sql+=" WHERE "+param;
}
Object by = formMap.get("$orderby");
if(null!=by){
sql+= " "+by;
}
Object paging=formMap.get("paging");
if(null==paging){
throw new Exception("调用findByPage接口,必须传入PageView对象! formMap.set(\"paging\", pageView);");
}else if(StringUtils.isBlank(paging.toString())){
throw new Exception("调用findByPage接口,必须传入PageView对象! formMap.set(\"paging\", pageView);");
}
PageView pageView = (PageView) paging;
PagePlugin.setCount(sql, connection, boundSql, pageView);
sql=PagePlugin.generatePagesSql(sql, pageView);
}else if(Configuration.DELETEBYNAMES.equals(sqlId)){
sql = "delete from "+table.toString()+" where ";
String param = "";
for (Entry<String, Object> entry : formMap.entrySet()) {
if(!"ly_table".equals(entry.getKey())&&null!=entry.getValue()&&!"_t".equals(entry.getKey()))
param += " AND "+entry.getKey()+" IN ("+entry.getValue()+")";
}
if(StringUtils.isNotBlank(param)){
param=param.substring(param.indexOf("AND")+4);
sql+=param;
}
}else if(Configuration.DELETEBYATTRIBUTE.equals(sqlId)){
sql = "DELETE FROM "+table.toString()+" WHERE "+formMap.get("key");
if(null!=formMap.get("value"))
{
sql += " IN ("+formMap.get("value")+")";
}
}else if(Configuration.FINDBYNAMES.equals(sqlId)){
Map<String, Object> mapfield = SqlRunner.findByTablefield(connection, boundSql, table.toString());
String field = mapfield.get(Configuration.FIELD).toString();
String[] fe = field.split(",");
String param = "";
for (String string : fe) {
if(formMap.containsKey(string)){
Object v =formMap.get(string);
if(v.toString().indexOf("%")>-1)//处理模糊查询
{
param += " AND "+string+" LIKE '"+v+"'";
}else{
if(ResolverUtil.isNumeric1(v.toString())){
param += " AND "+string+" = "+v;
}else{
param += " AND "+string+" = '"+v+"'";
}
}
}
}
if(StringUtils.isNotBlank(param)){
param=param.substring(param.indexOf("AND")+4);
sql+=" WHERE "+param;
}
Object by = formMap.get("$orderby");
if(null!=by){
sql+= " "+by;
}
}else if(Configuration.FINDBYATTRIBUTE.equals(sqlId)){
sql = "SELECT * FROM "+table.toString()+" WHERE "+formMap.get("key");
if(null!=formMap.get("value")&&formMap.get("value").toString().indexOf("%")>-1)//处理模糊查询
{
sql += " LIKE '"+formMap.get("value")+"'";
}else{
Object v = formMap.get("value");
if(ResolverUtil.isNumeric1(v.toString())){
sql += " IN ("+v+")";
}else{
sql += " IN ('"+v+"')";
}
}
}else if(Configuration.ADDENTITY.equals(sqlId)){
Map<String, Object> mapfield = SqlRunner.findByTablefield(connection, boundSql, table.toString());
String field = mapfield.get(Configuration.FIELD).toString();
String[] fe = field.split(",");
String fieldString = "";
String fieldValues = "";
for (String string : fe) {
Object v=formMap.get(string);
if(null!=v&&!StringUtils.isBlank(v.toString())){
fieldString+=string+",";
fieldValues+="'"+v+"',";
}
}
sql = "INSERT INTO "+table.toString()+" ("+ResolverUtil.trimComma(fieldString)+") values ("+ResolverUtil.trimComma(fieldValues)+")";
}else if(Configuration.EDITENTITY.equals(sqlId)){
Map<String, Object> mapfield = SqlRunner.findByTablefield(connection, boundSql, table.toString());
String field = mapfield.get(Configuration.FIELD).toString();
String[] fe = field.split(",");
String fieldString = "";
String where = "";
for (String string : fe) {
Object v=formMap.get(string);
if(null!=v&&!StringUtils.isBlank(v.toString())){
String key = mapfield.get(Configuration.COLUMN_KEY).toString();
if(!StringUtils.isBlank(key)){
if(key.equals(string)){
where = "WHERE "+key+" = '"+v+"'";
}else{
fieldString+=string+"='"+v+"',";
}
}else{
throw new NullPointerException("update操作没有找到主键!");
}
}
}
sql = "UPDATE "+table.toString()+" SET "+ResolverUtil.trimComma(fieldString)+" "+where;
}else if(Configuration.FINDBYFRIST.equals(sqlId)){
sql = "SELECT * FROM "+table.toString()+" WHERE "+formMap.get("key");
if(null!=formMap.get("value")&&!"".equals(formMap.get("value").toString()))//处理模糊查询
{
sql += " = '"+formMap.get("value")+"'";
}else{
throw new Exception(sqlId+" 调用公共方法异常!,传入参数错误!");
}
}else if(Configuration.BATCHSAVE.equals(sqlId)){
Map<String, Object> mapfield = null;
String field = null;
if(null!=formMaps&&formMaps.size()>0){
table = Common.toHashMap(formMaps.get(0)).get(Configuration.LY_TABLE);
mapfield=SqlRunner.findByTablefield(connection, boundSql, table.toString());
field=mapfield.get(Configuration.FIELD).toString();
}
sql = "INSERT INTO "+table.toString();
String fieldString = "";
String fs = "";
String fd = "";
String fieldValues = "";
String fvs = "";
for (int i = 0; i < formMaps.size(); i++) {
Object object = formMaps.get(i);
Map<String, Object> froMmap = (Map<String, Object>) object;
String[] fe = field.split(",");
for (String string : fe) {
Object v=froMmap.get(string);
if(null!=v&&!StringUtils.isBlank(v.toString())){
fieldString+=string+",";
fieldValues+="'"+v+"',";
}
}
if(i==0){
fd=fieldString;
}
fvs +="("+ResolverUtil.trimComma(fieldValues)+"),";
fs +=" INSERT INTO "+table.toString()+" ("+ResolverUtil.trimComma(fieldString)+") VALUES ("+ResolverUtil.trimComma(fieldValues)+");";
fieldValues = "";
fieldString= "";
}
String v = ResolverUtil.trimComma(fvs);
sql = "INSERT INTO "+table.toString()+" ("+ResolverUtil.trimComma(fd)+") VALUES "+ResolverUtil.trimComma(fvs)+"";
String[] vs = v.split("\\),");
boolean b = false;
for (String string : vs) {
if(string.split(",").length!=fd.split(",").length){
b=true;
}
}
if(b){
sql = fs.substring(0,fs.length()-1);
}
}else{
throw new Exception("调用公共方法异常!");
}
return sql.toUpperCase();
}
}