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 io.jboot.aop.annotation.DefaultValue;
019import io.jboot.apidoc.annotation.ApiPara;
020import io.jboot.apidoc.annotation.ApiParas;
021import io.jboot.utils.ClassType;
022import io.jboot.utils.ClassUtil;
023import io.jboot.web.json.JsonBody;
024
025import javax.validation.constraints.*;
026import java.io.Serializable;
027import java.lang.reflect.Method;
028import java.lang.reflect.Parameter;
029import java.lang.reflect.Type;
030import java.util.LinkedList;
031import java.util.List;
032import java.util.Map;
033
034public class ApiOperation implements Serializable {
035
036    private String value; //标题
037    private String notes; //描述
038    private String paraNotes; //参数描述,对所有参数的描述
039    private int orderNo; //排序序号
040
041    private String actionKey; // 路径
042    private ContentType contentType;
043    private List<ApiParameter> apiParameters; //所有的参数
044
045    private ClassType retType; //响应类型
046    private String retMockJson; //响应 mock json
047    private Map<String, List<ApiResponse>> retRemarks; //响应的字段备注(描述),key 类名的简称,value 类名的字段
048
049
050    private Class<?> controllerClass; //所在的类
051    private Method method; //对应的方法
052
053
054    public ApiOperation() {
055    }
056
057    public String getValue() {
058        return value;
059    }
060
061    public void setValue(String value) {
062        this.value = value;
063    }
064
065    public String getNotes() {
066        return notes;
067    }
068
069    public void setNotes(String notes) {
070        this.notes = notes;
071    }
072
073    public String getParaNotes() {
074        return paraNotes;
075    }
076
077    public void setParaNotes(String paraNotes) {
078        this.paraNotes = paraNotes;
079    }
080
081    public int getOrderNo() {
082        return orderNo;
083    }
084
085    public void setOrderNo(int orderNo) {
086        this.orderNo = orderNo;
087    }
088
089    public String getActionKey() {
090        return actionKey;
091    }
092
093    public void setActionKey(String actionKey) {
094        this.actionKey = actionKey;
095    }
096
097    public ContentType getContentType() {
098        return contentType;
099    }
100
101    public void setContentType(ContentType contentType) {
102        this.contentType = contentType;
103    }
104
105    public List<ApiParameter> getApiParameters() {
106        return apiParameters;
107    }
108
109    public void setApiParameters(List<ApiParameter> apiParameters) {
110        this.apiParameters = apiParameters;
111    }
112
113    public void addApiParameter(ApiParameter parameter) {
114        if (apiParameters == null) {
115            apiParameters = new LinkedList<>();
116        }
117        apiParameters.add(parameter);
118    }
119
120    public boolean hasParameter() {
121        return apiParameters != null && apiParameters.size() > 0;
122    }
123
124    public ClassType getRetType() {
125        return retType;
126    }
127
128    public void setRetType(ClassType retType) {
129        this.retType = retType;
130    }
131
132    public Method getMethod() {
133        return method;
134    }
135
136    public void setMethod(Method method) {
137        this.method = method;
138    }
139
140    public Class<?> getControllerClass() {
141        return controllerClass;
142    }
143
144    public void setControllerClass(Class<?> controllerClass) {
145        this.controllerClass = controllerClass;
146    }
147
148
149    public void setMethodAndInfo(Method method, String controllerPath, HttpMethod[] defaultMethods, Class<?> containerClass) {
150
151        this.method = method;
152        this.actionKey = ApiDocUtil.getActionKey(method, controllerPath);
153        this.retType = ClassUtil.getClassType(method.getGenericReturnType(), getControllerClass());
154
155        if (retType.isVoid() && containerClass != null) {
156            retType = new ClassType(containerClass);
157        }
158
159        this.retMockJson = ApiDocManager.me().buildMockJson(retType, method);
160        this.retRemarks = ApiDocManager.me().buildRemarks(retType, method);
161
162        setParameters(method, defaultMethods);
163    }
164
165
166    private void setParameters(Method method, HttpMethod[] defaultMethods) {
167        ApiParas apiParas = method.getAnnotation(ApiParas.class);
168        if (apiParas != null) {
169            for (ApiPara apiPara : apiParas.value()) {
170                addApiParameter(new ApiParameter(apiPara, defaultMethods));
171            }
172        }
173
174        ApiPara apiPara = method.getAnnotation(ApiPara.class);
175        if (apiPara != null) {
176            addApiParameter(new ApiParameter(apiPara, defaultMethods));
177        }
178
179        Parameter[] parameters = method.getParameters();
180        Type[] paraTypes = method.getGenericParameterTypes();
181        for (int i = 0; i < parameters.length; i++) {
182
183            ApiParameter apiParameter = new ApiParameter();
184            Parameter parameter = parameters[i];
185            apiParameter.setName(parameter.getName());
186            apiParameter.setDataType(ClassUtil.getClassType(paraTypes[i], getControllerClass()));
187
188            if (parameter.getAnnotation(JsonBody.class) != null) {
189                apiParameter.setHttpMethods(new HttpMethod[]{HttpMethod.POST});
190            } else {
191                apiParameter.setHttpMethods(defaultMethods);
192            }
193
194            ApiPara paraAnnotation = parameter.getAnnotation(ApiPara.class);
195            if (paraAnnotation != null) {
196                apiParameter.setValue(paraAnnotation.value());
197                apiParameter.setNotes(paraAnnotation.notes());
198
199                if (paraAnnotation.method().length > 0) {
200                    apiParameter.setHttpMethods(paraAnnotation.method());
201                }
202
203                if (paraAnnotation.require()) {
204                    apiParameter.setNotBlank(true);
205                    apiParameter.setRequire(true);
206                }
207            }
208
209            if (parameter.getAnnotation(NotNull.class) != null) {
210                apiParameter.setRequire(true);
211            }
212
213            if (parameter.getAnnotation(NotBlank.class) != null) {
214                apiParameter.setNotBlank(true);
215                apiParameter.setRequire(true);
216            }
217
218            if (parameter.getAnnotation(NotEmpty.class) != null) {
219                apiParameter.setNotEmpty(true);
220                apiParameter.setRequire(true);
221            }
222
223            if (parameter.getAnnotation(Email.class) != null) {
224                apiParameter.setEmail(true);
225                apiParameter.setRequire(true);
226            }
227
228            Min min = parameter.getAnnotation(Min.class);
229            if (min != null) {
230                apiParameter.setMin(min.value());
231                apiParameter.setRequire(true);
232            }
233
234            Max max = parameter.getAnnotation(Max.class);
235            if (max != null) {
236                apiParameter.setMax(max.value());
237                apiParameter.setRequire(true);
238            }
239
240            Pattern pattern = parameter.getAnnotation(Pattern.class);
241            if (pattern != null) {
242                apiParameter.setPattern(pattern.regexp());
243                apiParameter.setRequire(true);
244            }
245
246            DefaultValue defaultValue = parameter.getAnnotation(DefaultValue.class);
247            if (defaultValue != null) {
248                apiParameter.setDefaultValue(defaultValue.value());
249            }
250
251            addApiParameter(apiParameter);
252        }
253    }
254
255    public String getRetMockJson() {
256        return retMockJson;
257    }
258
259    public void setRetMockJson(String retMockJson) {
260        this.retMockJson = retMockJson;
261    }
262
263    public Map<String, List<ApiResponse>> getRetRemarks() {
264        return retRemarks;
265    }
266
267    public void setRetRemarks(Map<String, List<ApiResponse>> retRemarks) {
268        this.retRemarks = retRemarks;
269    }
270
271    @Override
272    public String toString() {
273        return "ApiOperation{" +
274                "value='" + value + '\'' +
275                ", notes='" + notes + '\'' +
276                ", actionKey='" + actionKey + '\'' +
277                '}';
278    }
279}