All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.moon.runner.core.InvokeArgs1 Maven / Gradle / Ivy

package com.moon.runner.core;

import com.moon.runner.core.InvokeEnsure.EnsureArgs1;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.moon.core.lang.ClassUtil.toPrimitiveClass;
import static com.moon.core.lang.ThrowUtil.noInstanceError;
import static com.moon.core.lang.reflect.MethodUtil.invoke;

/**
 * @author moonsky
 */
final class InvokeArgs1 extends InvokeAbstract {

    private InvokeArgs1() { noInstanceError(); }

    static class OneStaticDynamic implements AsInvoker {

        final Method srcMethod;
        final AsRunner paramValuer;
        final Set> METHODS_SET;

        Method currentMethod;

        OneStaticDynamic(AsRunner paramValuer, List methods) {
            final Map methodsMap = new HashMap<>();
            methods.forEach(m -> methodsMap.put(m.getParameterTypes()[0], m));
            METHODS_SET = methodsMap.entrySet();
            this.paramValuer = paramValuer;
            srcMethod = methods.get(0);
        }

        private final Method withCustom(Class dataType) {
            Class currType, prevType = null;
            Method method = null, tmp;
            Set> methodsSet = this.METHODS_SET;
            for (Map.Entry entry : methodsSet) {
                if ((currType = entry.getKey()).isAssignableFrom(dataType)) {
                    if (prevType == null || prevType.isAssignableFrom(currType)) {
                        method = entry.getValue();
                        prevType = currType;
                    }
                }
            }
            if (method == null) {
                for (Map.Entry entry : methodsSet) {
                    if ((tmp = entry.getValue()).isVarArgs()) {
                        currType = entry.getKey().getComponentType();
                        if (currType.isAssignableFrom(dataType)) {
                            if (prevType == null || prevType.isAssignableFrom(currType)) {
                                prevType = currType;
                                method = tmp;
                            }
                        }
                    }
                }
            }
            return method;
        }

        private final Method withPrimitive(final Class dataType, final Class currType) {
            Class temp;
            Method method = null, tmp;
            boolean isPrimitive = false;
            Set> methodsSet = this.METHODS_SET;
            for (Map.Entry entry : methodsSet) {
                temp = entry.getKey();
                if (temp == currType) {
                    method = entry.getValue();
                    break;
                } else if (temp == dataType) {
                    method = entry.getValue();
                }
            }
            if (method == null) {
                for (Map.Entry entry : methodsSet) {
                    if ((tmp = entry.getValue()).isVarArgs()) {
                        temp = entry.getKey().getComponentType();
                        if (temp == currType) {
                            isPrimitive = true;
                            method = tmp;
                            break;
                        } else if (temp == dataType && !isPrimitive) {
                            method = tmp;
                        }
                    }
                }
            }
            return method;
        }

        private final Method withNumber(final Class dataType, Class currType) {
            Class temp;
            Method method = null, tmp;
            boolean isPrimitive = false;
            Set> methodsSet = this.METHODS_SET;
            final int origin = getOrdinal(currType);
            int currOrdinal = MAX_ORDINAL, ordinal;
            for (Map.Entry entry : methodsSet) {
                if ((temp = entry.getKey()).isPrimitive()) {
                    ordinal = getOrdinal(temp);
                    if (ordinal >= origin && ordinal <= currOrdinal) {
                        method = entry.getValue();
                        currOrdinal = ordinal;
                        isPrimitive = true;
                    }
                } else if (dataType == temp && !isPrimitive) {
                    method = entry.getValue();
                }
            }
            if (method == null) {
                for (Map.Entry entry : methodsSet) {
                    if ((tmp = entry.getValue()).isVarArgs()) {
                        temp = entry.getKey().getComponentType();
                        ordinal = getOrdinal(temp);
                        if (ordinal >= origin && ordinal <= currOrdinal) {
                            currOrdinal = ordinal;
                            isPrimitive = true;
                            method = tmp;
                        } else if (dataType == temp && !isPrimitive) {
                            method = tmp;
                        }
                    }
                }
            }
            return method;
        }

        private final Method reloadMethod(Object data) {
            Class dataType = data.getClass();
            Class currType = toPrimitiveClass(dataType);
            Method method;
            if (currType == null) {
                method = withCustom(dataType);
            } else if (currType == boolean.class || currType == char.class) {
                method = withPrimitive(dataType, currType);
            } else {
                method = withNumber(dataType, currType);
            }
            if (method == null) {
                ParseUtil.doThrow(toString());
            }
            return currentMethod = method;
        }

        Method getMethod(Object data) { return currentMethod == null ? reloadMethod(data) : currentMethod; }

        @Override
        public Object run(Object data) {
            Object param = paramValuer.run(data);
            try {
                return invoke(true, getMethod(param), null, param);
            } catch (Throwable t) {
                return invoke(true, reloadMethod(param), null, param);
            }
        }

        @Override
        public String toString() { return stringify(srcMethod); }
    }

    static AsRunner staticCall1(Class type, String name, AsRunner paramValuer) {
        List ms = filterByParamCount(staticMethods(type, name), 1);
        switch (ms.size()) {
            case 0:
                return ParseUtil.doThrow(type, name);
            case 1:
                return ensure(ms.get(0), paramValuer);
            default:
                return new OneStaticDynamic(paramValuer, ms);
        }
    }

    static AsRunner memberCall1(Class type, String name, AsValuer src, AsRunner no1) {
        List ms = memberMethods(type, name);
        switch (ms.size()) {
            case 0:
                return doThrowNull();
            case 1:
                return new EnsureArgs1(ms.get(0), src, no1);
            default:
                return new InvokeOne(src, no1, name);
        }
    }

    final static AsRunner parse(
        AsValuer prev, String name, boolean isStatic, AsRunner no1
    ) {
        if (isStatic) {
            // 静态方法
            Class type = ((DataClass) prev).getValue();
            return staticCall1(type, name, no1);
        } else if (prev.isConst()) {
            Class target = prev.run().getClass();
            return memberCall1(target, name, prev, no1);
        } else {
            // 成员方法
            return new InvokeOne(prev, no1, name);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy