/*
 * Copyright 2016-2018 shardingsphere.io.
 * <p>
 * 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.
 * </p>
 */

package io.shardingsphere.core.jdbc.adapter;

import io.shardingsphere.core.exception.ShardingException;
import io.shardingsphere.core.jdbc.adapter.invocation.JdbcMethodInvocation;

import java.sql.SQLException;
import java.sql.Wrapper;
import java.util.ArrayList;
import java.util.Collection;

/**
 * Adapter for {@code Wrapper}.
 * 
 * @author zhangliang
 */
public class WrapperAdapter implements Wrapper {
    
    private final Collection<JdbcMethodInvocation> jdbcMethodInvocations = new ArrayList<>();
    
    @SuppressWarnings("unchecked")
    @Override
    public final <T> T unwrap(final Class<T> iface) throws SQLException {
        if (isWrapperFor(iface)) {
            return (T) this;
        }
        throw new SQLException(String.format("[%s] cannot be unwrapped as [%s]", getClass().getName(), iface.getName()));
    }
    
    @Override
    public final boolean isWrapperFor(final Class<?> iface) {
        return iface.isInstance(this);
    }
    
    /**
     * 记录方法调用.
     * 
     * @param targetClass 目标类
     * @param methodName 方法名称
     * @param argumentTypes 参数类型
     * @param arguments 参数
     */
    public final void recordMethodInvocation(final Class<?> targetClass, final String methodName, final Class<?>[] argumentTypes, final Object[] arguments) {
        try {
            jdbcMethodInvocations.add(new JdbcMethodInvocation(targetClass.getMethod(methodName, argumentTypes), arguments));
        } catch (final NoSuchMethodException ex) {
            throw new ShardingException(ex);
        }
    }
    
    /**
     * 回放记录的方法调用.
     * 
     * @param target 目标对象
     */
    public final void replayMethodsInvocation(final Object target) {
        for (JdbcMethodInvocation each : jdbcMethodInvocations) {
            each.invoke(target);
        }
    }
    
    protected final void throwSQLExceptionIfNecessary(final Collection<SQLException> exceptions) throws SQLException {
        if (exceptions.isEmpty()) {
            return;
        }
        SQLException ex = new SQLException();
        for (SQLException each : exceptions) {
            ex.setNextException(each);
        }
        throw ex;
    }
}

@@ -1602,14 +1602,32 @@
   * 
-%E8%AE%B0%E5%BD%95%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8
+record method invocation
 .%0A  
@@ -1662,11 +1662,20 @@
 ass 
-%E7%9B%AE%E6%A0%87%E7%B1%BB
+target class
 %0A   
@@ -1700,12 +1700,19 @@
 ame 
-%E6%96%B9%E6%B3%95%E5%90%8D%E7%A7%B0
+method name
 %0A   
@@ -1740,12 +1740,22 @@
 pes 
-%E5%8F%82%E6%95%B0%E7%B1%BB%E5%9E%8B
+argument types
 %0A   
@@ -1779,10 +1779,17 @@
 nts 
-%E5%8F%82%E6%95%B0
+arguments
 %0A   
@@ -2227,17 +2227,33 @@
   * 
-%E5%9B%9E%E6%94%BE%E8%AE%B0%E5%BD%95%E7%9A%84%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8
+Replay methods invocation
 .%0A  
@@ -2283,12 +2283,21 @@
 get 
-%E7%9B%AE%E6%A0%87%E5%AF%B9%E8%B1%A1
+target object
 %0A   

refine javadoc