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

ars.invoke.local.Apis Maven / Gradle / Ivy

The newest version!
package ars.invoke.local;

import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.regex.Pattern;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.annotation.Annotation;

import ars.util.Beans;
import ars.util.Strings;
import ars.util.SimpleTree;
import ars.invoke.Router;
import ars.invoke.Channel;
import ars.invoke.Context;
import ars.invoke.Messager;
import ars.invoke.request.Token;
import ars.invoke.request.Session;
import ars.invoke.request.Requester;
import ars.invoke.request.SessionFactory;
import ars.invoke.request.ParameterInvalidException;

/**
 * 接口工具类
 *
 * @author wuyongqiang
 */
public final class Apis {
    private Apis() {

    }

    /**
     * 获取所有使用了Api注解的公共类
     *
     * @param packages 包路径数组
     * @return 类对象集合
     */
    public static List> getApiClasses(String... packages) {
        if (packages == null || packages.length == 0) {
            throw new IllegalArgumentException("Packages must not be empty");
        }
        List> classes = new LinkedList>();
        for (String pack : packages) {
            List> metas = Beans.getClasses(pack);
            for (Class meta : metas) {
                if (meta.isAnnotationPresent(Api.class)) {
                    classes.add(meta);
                }
            }
        }
        return classes;
    }

    /**
     * 获取使用了Api注解的公共类
     *
     * @param cls 类对象
     * @return 类对象
     */
    public static Class getApiClass(Class cls) {
        if (cls == null) {
            throw new IllegalArgumentException("Class must not be null");
        }
        if (cls.isAnnotationPresent(Api.class)) {
            return cls;
        }
        Class[] interfaces = cls.getInterfaces();
        for (Class c : interfaces) {
            Class apiClass = getApiClass(c);
            if (apiClass != null) {
                return apiClass;
            }
        }
        Class parent = cls.getSuperclass();
        return parent == null ? null : getApiClass(parent);
    }

    /**
     * 获取类中使用了Api注解的公共方法
     *
     * @param cls 类
     * @return 方法数组
     */
    public static Method[] getApiMethods(Class cls) {
        if (cls == null) {
            throw new IllegalArgumentException("Class must not be null");
        }
        List methods = _getApiMethods(cls);
        if (methods.isEmpty()) {
            return new Method[0];
        }
        Set apis = new HashSet(methods.size());
        Iterator iterator = methods.iterator();
        while (iterator.hasNext()) {
            String api = getApi(iterator.next());
            if (apis.contains(api)) {
                iterator.remove();
            } else {
                apis.add(api);
            }
        }
        return methods.toArray(new Method[0]);
    }

    /**
     * 获取类中使用了Api注解的公共方法
     *
     * @param cls 类
     * @return 方法数组
     */
    private static List _getApiMethods(Class cls) {
        List methods = new LinkedList();
        for (Method method : cls.getMethods()) {
            if (method.isAnnotationPresent(Api.class)) {
                methods.add(method);
            }
        }
        Class[] interfaces = cls.getInterfaces();
        for (Class c : interfaces) {
            methods.addAll(_getApiMethods(c));
        }
        Class parent = cls.getSuperclass();
        if (parent != null) {
            methods.addAll(_getApiMethods(parent));
        }
        return methods;
    }

    /**
     * 获取类接口地址
     *
     * @param cls 类对象
     * @return 接口地址
     */
    public static String getApi(Class cls) {
        if (cls == null) {
            throw new IllegalArgumentException("Class must not be null");
        }
        if (!cls.isAnnotationPresent(Api.class)) {
            return null;
        }
        String api = cls.getAnnotation(Api.class).value();
        return api.isEmpty() ? Strings.replace(cls.getName(), '.', '/') : api;
    }

    /**
     * 获取方法接口地址
     *
     * @param method 方法对象
     * @return 接口地址
     */
    public static String getApi(Method method) {
        if (method == null) {
            throw new IllegalArgumentException("Method must not be null");
        }
        if (!method.isAnnotationPresent(Api.class)) {
            return null;
        }
        String api = method.getAnnotation(Api.class).value();
        return api.isEmpty() ? method.getName() : api;
    }

    /**
     * 获取方法接口条件
     *
     * @param method 方法对象
     * @return 条件对象数组
     */
    public static Argument[] getArguments(Method method) {
        if (method == null) {
            throw new IllegalArgumentException("Method must not be null");
        }
        Class[] types = method.getParameterTypes();
        Argument[] arguments = new Argument[types.length];
        Annotation[][] annotations = method.getParameterAnnotations();
        outer:
        for (int i = 0; i < types.length; i++) {
            for (Annotation annotation : annotations[i]) {
                if (annotation.annotationType() == Param.class) {
                    Param param = (Param) annotation;
                    String name = param.name().trim();
                    String value = param.value().trim();
                    String regex = param.regex().trim();
                    Class adapter = param.adapter();
                    Argument argument = new Argument();
                    argument.setType(types[i]);
                    if (!name.isEmpty()) {
                        argument.setName(name);
                    }
                    if (!value.isEmpty()) {
                        argument.setValue(value);
                    }
                    if (!regex.isEmpty()) {
                        argument.setPattern(Pattern.compile(regex));
                    }
                    if (adapter != ParamAdapter.class) {
                        argument.setAdapter(Beans.getInstance(adapter));
                    }
                    argument.setRequired(param.required());
                    arguments[i] = argument;
                    continue outer;
                }
            }
        }
        return arguments;
    }

    /**
     * 获取本地接口方法参数
     *
     * @param requester 请求对象
     * @param function  本地资源对象
     * @return 本地接口方法参数数组
     * @throws Exception 操作异常
     */
    public static Object[] getParameters(Requester requester, Function function) throws Exception {
        if (requester == null) {
            throw new IllegalArgumentException("Requester must not be null");
        }
        Argument[] arguments = function.getArguments();
        Class[] types = function.getMethod().getParameterTypes();
        Object[] parameters = new Object[arguments.length];
        Map condtions = new HashMap(requester.getParameters());
        for (int i = 0; i < arguments.length; i++) {
            Class type = types[i];
            Argument argument = arguments[i];
            if (argument == null) {
                if (Router.class.isAssignableFrom(type)) {
                    parameters[i] = requester.getChannel().getContext().getRouter();
                } else if (Channel.class.isAssignableFrom(type)) {
                    parameters[i] = requester.getChannel();
                } else if (Context.class.isAssignableFrom(type)) {
                    parameters[i] = requester.getChannel().getContext();
                } else if (Messager.class.isAssignableFrom(type)) {
                    parameters[i] = requester.getChannel().getContext().getMessager();
                } else if (Requester.class.isAssignableFrom(type)) {
                    parameters[i] = requester;
                } else if (Token.class.isAssignableFrom(type)) {
                    parameters[i] = requester.getToken();
                } else if (Session.class.isAssignableFrom(type)) {
                    parameters[i] = requester.getSession();
                } else if (SessionFactory.class.isAssignableFrom(type)) {
                    parameters[i] = requester.getSession().getSessionFactory();
                } else if (Map.class.isAssignableFrom(type)) {
                    parameters[i] = condtions;
                } else {
                    parameters[i] = requester.getChannel().getContext().getBean(type);
                }
            } else if (argument.getAdapter() == null) {
                String name = argument.getName();
                try {
                    if (name == null) {
                        if (Beans.isMetaClass(type)) {
                            parameters[i] = Beans.toObject(type, argument.getValue());
                        } else {
                            Object instance = Beans.getInstance(type);
                            if (!condtions.isEmpty()) {
                                while (type != Object.class) {
                                    Field[] fields = type.getDeclaredFields();
                                    for (Field field : fields) {
                                        if (condtions.containsKey(field.getName())
                                            && !Modifier.isStatic(field.getModifiers())) {
                                            Object value = condtions.remove(field.getName());
                                            if (value == null) {
                                                continue;
                                            }
                                            field.setAccessible(true);
                                            try {
                                                field.set(instance, Beans.toObject(field.getType(), value));
                                            } catch (IllegalAccessException e) {
                                                throw new RuntimeException(e);
                                            } finally {
                                                field.setAccessible(false);
                                            }
                                        }
                                    }
                                    type = type.getSuperclass();
                                }
                            }
                            parameters[i] = instance;
                        }
                    } else {
                        Object value = condtions.remove(name);
                        if (value == null) {
                            value = argument.getValue();
                        }
                        if (argument.getPattern() != null && value instanceof CharSequence
                            && !argument.getPattern().matcher((CharSequence) value).matches()) {
                            throw new ParameterInvalidException(name, "invalid");
                        }
                        parameters[i] = Beans.toObject(type, value);
                    }
                } catch (IllegalArgumentException e) {
                    throw new ParameterInvalidException(name, e.getMessage());
                }
            } else {
                parameters[i] = argument.getAdapter().adaption(requester, type);
            }
            if (argument != null && argument.isRequired() && Beans.isEmpty(arguments[i])) {
                throw new ParameterInvalidException(argument.getName(), "required");
            }
        }
        return parameters;
    }

    /**
     * 获取接口地址树
     *
     * @param apis 接口地址集合
     * @return 树列表
     */
    public static List getTrees(Collection apis) {
        if (apis == null) {
            throw new IllegalArgumentException("Apis must not be null");
        }
        List roots = new ArrayList(apis.size());
        Map trees = new HashMap(apis.size());
        for (String api : apis) {
            if (api.equals("/")) {
                SimpleTree tree = new SimpleTree(api);
                roots.add(tree);
                continue;
            }
            int from = -1, last = -1;
            while ((from = api.indexOf('/', from + 1)) > -1) {
                last = from;
                String id = api.substring(0, from);
                if (trees.containsKey(id)) {
                    continue;
                }
                int index = id.lastIndexOf('/');
                SimpleTree tree = new SimpleTree(id);
                if (index < 0) {
                    roots.add(tree);
                } else {
                    SimpleTree parent = trees.get(id.substring(0, index));
                    tree.setParent(parent);
                    parent.getChildren().add(tree);
                }
                trees.put(id, tree);
            }
            if (last < api.length() - 1) {
                SimpleTree leaf = new SimpleTree(api);
                SimpleTree parent = trees.get(api.substring(0, last));
                leaf.setParent(parent);
                parent.getChildren().add(leaf);
                trees.put(api, leaf);
            }
        }
        return roots;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy