// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/exceptions/SurgeonException.java
// public class SurgeonException extends Exception {
// 
//     public SurgeonException() {
//         super();
//     }
// 
//     public SurgeonException(String message) {
//         super(message);
//     }
// 
//     public SurgeonException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public SurgeonException(Throwable cause) {
//         super(cause);
//     }
// }
// 
// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/interfaces/Continue.java
// public interface Continue {
// }
// 
// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/interfaces/IMaster.java
// public interface IMaster {
//     /**
//      * @param function The key of SurgeonMethod
//      */
//     SurgeonMethod find(String function);
// }
// 
// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/interfaces/ISurgeon.java
// public interface ISurgeon {
// 
//     /**
//      * Control current object to singleton.
//      */
//     boolean singleton();
// }
// 
// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/interfaces/Replacer.java
// public interface Replacer<T> {
//     /**
//      * Called before original function called.
//      *
//      * @param params The original function input params.
//      */
//     void before(Object[] params);
// 
//     /**
//      * Replace original function.
//      *
//      * @param params The original function input params.
//      * @return new return result.
//      */
//     T replace(Object[] params) throws Throwable;
// 
//     /**
//      * Called after original function called.
//      *
//      * @param params The original function input params.
//      */
//     void after(Object[] params);
// }


import com.surgeon.weaving.core.exceptions.SurgeonException;
import com.surgeon.weaving.core.interfaces.Continue;
import com.surgeon.weaving.core.interfaces.IMaster;
import com.surgeon.weaving.core.interfaces.ISurgeon;
import com.surgeon.weaving.core.interfaces.Replacer;
import java.lang.reflect.InvocationTargetException;
import static android.text.TextUtils.isEmpty;
import static com.surgeon.weaving.core.ASPConstant.AFTER;
import static com.surgeon.weaving.core.ASPConstant.BEFORE;
                         Object target,
                         Object[] args) throws Throwable {
        if (isEmpty(namespace) || isEmpty(function)) return Continue.class;
        try {
            String masterPath = PREFIX + namespace.replace(".", "_");
            IMaster master = InnerCache.getInstance().getMaster(masterPath);
            if (master == null) {
                Class<?> clazz = Class.forName(masterPath);
                master = (IMaster) clazz.newInstance();
                InnerCache.getInstance().putMaster(masterPath, master);
            }

            //copy args
            Object[] copyOfArgs = new Object[args.length + 1];
            System.arraycopy(args, 0, copyOfArgs, 1, args.length);
            copyOfArgs[0] = target;

            //runtime repalce
            Object wrapper;
            String runtimeKey = namespace + "." + function;
            if (AFTER.equals(prefix)) {
                wrapper = InnerCache.getInstance().popReplaceWapper(runtimeKey);
            } else {
                wrapper = InnerCache.getInstance().getReplaceWapper(runtimeKey);
            }

            if (wrapper != Continue.class) {
                ReplaceWapper resultWapper = (ReplaceWapper) wrapper;
                if (!resultWapper.isReplacer()) return resultWapper.getResult();

// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/exceptions/SurgeonException.java
// public class SurgeonException extends Exception {
// 
//     public SurgeonException() {
//         super();
//     }
// 
//     public SurgeonException(String message) {
//         super(message);
//     }
// 
//     public SurgeonException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public SurgeonException(Throwable cause) {
//         super(cause);
//     }
// }
// 
// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/interfaces/Continue.java
// public interface Continue {
// }
// 
// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/interfaces/IMaster.java
// public interface IMaster {
//     /**
//      * @param function The key of SurgeonMethod
//      */
//     SurgeonMethod find(String function);
// }
// 
// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/interfaces/ISurgeon.java
// public interface ISurgeon {
// 
//     /**
//      * Control current object to singleton.
//      */
//     boolean singleton();
// }
// 
// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/interfaces/Replacer.java
// public interface Replacer<T> {
//     /**
//      * Called before original function called.
//      *
//      * @param params The original function input params.
//      */
//     void before(Object[] params);
// 
//     /**
//      * Replace original function.
//      *
//      * @param params The original function input params.
//      * @return new return result.
//      */
//     T replace(Object[] params) throws Throwable;
// 
//     /**
//      * Called after original function called.
//      *
//      * @param params The original function input params.
//      */
//     void after(Object[] params);
// }


// Path: surgeon-core/src/main/java/com/surgeon/weaving/core/MasterFinder.java
import com.surgeon.weaving.core.exceptions.SurgeonException;
import com.surgeon.weaving.core.interfaces.Continue;
import com.surgeon.weaving.core.interfaces.IMaster;
import com.surgeon.weaving.core.interfaces.ISurgeon;
import com.surgeon.weaving.core.interfaces.Replacer;
import java.lang.reflect.InvocationTargetException;
import static android.text.TextUtils.isEmpty;
import static com.surgeon.weaving.core.ASPConstant.AFTER;
import static com.surgeon.weaving.core.ASPConstant.BEFORE;

                         Object target,
                         Object[] args) throws Throwable {
        if (isEmpty(namespace) || isEmpty(function)) return Continue.class;
        try {
            String masterPath = PREFIX + namespace.replace(".", "_");
            IMaster master = InnerCache.getInstance().getMaster(masterPath);
            if (master == null) {
                Class<?> clazz = Class.forName(masterPath);
                master = (IMaster) clazz.newInstance();
                InnerCache.getInstance().putMaster(masterPath, master);
            }

            //copy args
            Object[] copyOfArgs = new Object[args.length + 1];
            System.arraycopy(args, 0, copyOfArgs, 1, args.length);
            copyOfArgs[0] = target;

            //runtime repalce
            Object wrapper;
            String runtimeKey = namespace + "." + function;
            if (AFTER.equals(prefix)) {
                wrapper = InnerCache.getInstance().popReplaceWapper(runtimeKey);
            } else {
                wrapper = InnerCache.getInstance().getReplaceWapper(runtimeKey);
            }

            if (wrapper != Continue.class) {
                ReplaceWapper resultWapper = (ReplaceWapper) wrapper;
                if (!resultWapper.isReplacer()) return resultWapper.getResult();

                Replacer replacer = (Replacer) resultWapper.getResult();