001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.jboot.apidoc;
017
018import com.alibaba.fastjson.JSONObject;
019import com.alibaba.fastjson.parser.Feature;
020import com.jfinal.config.Routes;
021import com.jfinal.core.ActionKey;
022import com.jfinal.core.Path;
023import com.jfinal.kit.StrKit;
024import io.jboot.apidoc.annotation.ApiResp;
025import io.jboot.apidoc.annotation.ApiResps;
026import io.jboot.core.listener.JbootAppListener;
027import io.jboot.core.listener.JbootAppListenerManager;
028import io.jboot.utils.AnnotationUtil;
029import io.jboot.utils.StrUtil;
030import io.jboot.web.controller.annotation.*;
031
032import java.lang.reflect.Method;
033import java.util.*;
034
035public class ApiDocUtil {
036
037
038    public static String getControllerPath(Class<?> controllerClass) {
039        RequestMapping rm = controllerClass.getAnnotation(RequestMapping.class);
040        if (rm != null) {
041            return AnnotationUtil.get(rm.value());
042        }
043
044        Path path = controllerClass.getAnnotation(Path.class);
045        if (path != null) {
046            return AnnotationUtil.get(path.value());
047        }
048
049        PostMapping pm = controllerClass.getAnnotation(PostMapping.class);
050        if (pm != null) {
051            return AnnotationUtil.get(pm.value());
052        }
053
054        GetMapping gm = controllerClass.getAnnotation(GetMapping.class);
055        if (gm != null) {
056            return AnnotationUtil.get(gm.value());
057        }
058
059
060        return tryToGetInAppListener(controllerClass);
061    }
062
063    private static Map<Class<?>, String> controllerPathMap = null;
064
065    private static String tryToGetInAppListener(Class<?> controllerClass) {
066
067        if (controllerPathMap != null) {
068            return controllerPathMap.get(controllerClass);
069        } else {
070            controllerPathMap = new HashMap<>();
071        }
072
073        List<JbootAppListener> listeners = JbootAppListenerManager.me().getListeners();
074        if (listeners == null || listeners.isEmpty()) {
075            return null;
076        }
077
078
079        Routes baseRoutes = new Routes() {
080            @Override
081            public void config() {
082            }
083
084            @Override
085            public Routes add(Routes childRoutes) {
086                childRoutes.config();
087                //all child routes
088                childRoutes.getRouteItemList()
089                        .forEach(route -> controllerPathMap.put(route.getControllerClass(), route.getControllerPath()));
090                return this;
091            }
092        };
093
094        listeners.forEach(jbootAppListener -> jbootAppListener.onRouteConfig(baseRoutes));
095
096        //base Routes
097        baseRoutes.getRouteItemList().forEach(route -> controllerPathMap.put(route.getControllerClass(), route.getControllerPath()));
098
099        return controllerPathMap.get(controllerClass);
100    }
101
102
103    public static HttpMethod getControllerMethod(Class<?> controllerClass) {
104        RequestMapping rm = controllerClass.getAnnotation(RequestMapping.class);
105        if (rm != null) {
106            return HttpMethod.ALL;
107        }
108
109        Path path = controllerClass.getAnnotation(Path.class);
110        if (path != null) {
111            return HttpMethod.ALL;
112        }
113
114        PostMapping pm = controllerClass.getAnnotation(PostMapping.class);
115        if (pm != null) {
116            return HttpMethod.POST;
117        }
118
119        GetMapping gm = controllerClass.getAnnotation(GetMapping.class);
120        if (gm != null) {
121            return HttpMethod.GET;
122        }
123        return HttpMethod.ALL;
124    }
125
126
127    public static HttpMethod[] getMethodHttpMethods(Method method, HttpMethod defaultMethod) {
128        Set<HttpMethod> httpMethods = new HashSet<>();
129        if (method.getAnnotation(GetRequest.class) != null) {
130            httpMethods.add(HttpMethod.GET);
131        }
132        if (method.getAnnotation(PostRequest.class) != null) {
133            httpMethods.add(HttpMethod.POST);
134        }
135        if (method.getAnnotation(PutRequest.class) != null) {
136            httpMethods.add(HttpMethod.PUT);
137        }
138        if (method.getAnnotation(DeleteRequest.class) != null) {
139            httpMethods.add(HttpMethod.DELETE);
140        }
141        if (method.getAnnotation(PatchRequest.class) != null) {
142            httpMethods.add(HttpMethod.PATCH);
143        }
144        return httpMethods.isEmpty() ? new HttpMethod[]{defaultMethod} : httpMethods.toArray(new HttpMethod[]{});
145    }
146
147
148    private static final String SLASH = "/";
149
150    public static String getActionKey(Method method, String controllerPath) {
151        String methodName = method.getName();
152        ActionKey ak = method.getAnnotation(ActionKey.class);
153        String actionKey;
154        if (ak != null) {
155            actionKey = ak.value().trim();
156
157            if (actionKey.startsWith(SLASH)) {
158                //actionKey = actionKey
159            } else if (actionKey.startsWith("./")) {
160                actionKey = controllerPath + actionKey.substring(1);
161            } else {
162                actionKey = SLASH + actionKey;
163            }
164        } else if (methodName.equals("index")) {
165            actionKey = controllerPath;
166        } else {
167            actionKey = controllerPath.equals(SLASH) ? SLASH + methodName : controllerPath + SLASH + methodName;
168        }
169
170        return actionKey;
171    }
172
173
174    public static List<ApiResponse> getApiResponseInMethod(Method method) {
175
176        List<ApiResponse> retList = new LinkedList<>();
177
178        ApiResps apiResps = method.getAnnotation(ApiResps.class);
179        if (apiResps != null) {
180            for (ApiResp apiResp : apiResps.value()) {
181                retList.add(new ApiResponse(apiResp));
182            }
183        }
184
185        ApiResp apiResp = method.getAnnotation(ApiResp.class);
186        if (apiResp != null) {
187            retList.add(new ApiResponse(apiResp));
188        }
189
190        return retList;
191    }
192
193
194    public static String prettyJson(String json) {
195        if (StrUtil.isBlank(json)) {
196            return json;
197        }
198        JSONObject jsonObject = null;
199        try {
200            jsonObject = JSONObject.parseObject(json, Feature.OrderedField);
201        } catch (Exception e) {
202            return json;
203        }
204        return JSONObject.toJSONString(jsonObject, true);
205    }
206
207
208    public static String getterMethod2Field(Method getterMethod) {
209        String methodName = getterMethod.getName();
210        if (methodName.startsWith("get") && methodName.length() > 3) {
211            return StrKit.firstCharToLowerCase(methodName.substring(3));
212        } else if (methodName.startsWith("is") && methodName.length() > 2) {
213            return StrKit.firstCharToLowerCase(methodName.substring(2));
214        }
215        return null;
216    }
217
218
219}