groupClassList = JavaClassUtil.getParamGroupJavaClass(annotation);
+ // Check if groupClasses contains any element from
+ // groupClassList
+ boolean hasGroup = groupClassList.stream().anyMatch(groupClasses::contains);
+
+ if (hasGroup) {
+ fieldJsonAnnotationInfo.setStrRequired(true);
+ } else if (CollectionUtil.isEmpty(groupClasses)) {
+ // If the annotation is @Valid or @Validated, the Default
+ // group is added by default and groupClasses will not be
+ // empty;
+ // In other cases, if groupClasses is still empty, then
+ // strRequired is false.
+ fieldJsonAnnotationInfo.setStrRequired(false);
+ }
+ }
+ // Handle @JsonFormat
+ if (DocAnnotationConstants.JSON_FORMAT.equals(annotationName)) {
+ fieldJsonAnnotationInfo.setFieldJsonFormatType(
+ DocUtil.processFieldTypeNameByJsonFormat(projectBuilder.getApiConfig().getShowJavaType(),
+ docField.getTypeFullyQualifiedName(), annotation));
+ fieldJsonAnnotationInfo
+ .setFieldJsonFormatValue(DocUtil.getJsonFormatString(docField.getJavaField(), annotation));
+ }
+
+ }
+ return fieldJsonAnnotationInfo;
+ }
+
+ /**
+ * Get the custom field information for a given field.
+ *
+ * @param projectBuilder the project builder
+ * @param docField the doc of java field
+ * @param customResponseField the custom response field
+ * @param customRequestField the custom request field
+ * @param isResp the response flag for the parameter
+ * @param simpleName the simple name of the field
+ * @return the custom field information {@link CustomFieldInfo}
+ */
+ protected CustomFieldInfo getCustomFieldInfo(ProjectDocConfigBuilder projectBuilder, DocJavaField docField,
+ CustomField customResponseField, CustomField customRequestField, boolean isResp, String simpleName) {
+ CustomFieldInfo customFieldInfo = new CustomFieldInfo();
+
+ // ignore custom field, if true return quickly
+ if (isIgnoreCustomField(docField, isResp, customRequestField, customResponseField)) {
+ customFieldInfo.setIgnore(true);
+ return customFieldInfo;
+ }
+
+ // cover response value
+ if (Objects.nonNull(customResponseField) && isResp && Objects.nonNull(customResponseField.getValue())
+ && JavaClassUtil.isTargetChildClass(simpleName, customResponseField.getOwnerClassName())) {
+
+ customFieldInfo.setFieldValue(String.valueOf(customResponseField.getValue()));
+ }
+
+ // cover request value
+ if (Objects.nonNull(customRequestField) && !isResp && Objects.nonNull(customRequestField.getValue())
+ && JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName())) {
+
+ customFieldInfo.setFieldValue(String.valueOf(customRequestField.getValue()));
+ }
+
+ // cover required
+ if (Objects.nonNull(customRequestField) && !isResp
+ && JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName())
+ && customRequestField.isRequire()) {
+
+ customFieldInfo.setStrRequired(true);
+ }
+
+ // cover comment
+ if (Objects.nonNull(customRequestField) && StringUtil.isNotEmpty(customRequestField.getDesc())
+ && JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName()) && !isResp) {
+ customFieldInfo.setComment(customRequestField.getDesc());
+ }
+ if (Objects.nonNull(customResponseField) && StringUtil.isNotEmpty(customResponseField.getDesc())
+ && JavaClassUtil.isTargetChildClass(simpleName, customResponseField.getOwnerClassName()) && isResp) {
+ customFieldInfo.setComment(customResponseField.getDesc());
+ }
+
+ // cover fieldName
+ if (Objects.nonNull(customRequestField) && StringUtil.isNotEmpty(customRequestField.getReplaceName())
+ && JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName()) && !isResp) {
+ customFieldInfo.setFieldName(customRequestField.getReplaceName());
+ }
+ if (Objects.nonNull(customResponseField) && StringUtil.isNotEmpty(customResponseField.getReplaceName())
+ && JavaClassUtil.isTargetChildClass(simpleName, customResponseField.getOwnerClassName()) && isResp) {
+
+ customFieldInfo.setFieldName(customResponseField.getReplaceName());
+ }
+ return customFieldInfo;
+ }
+
+}
diff --git a/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/doc/helper/ParamsBuildHelper.java b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/doc/helper/ParamsBuildHelper.java
new file mode 100644
index 00000000..67d0a09d
--- /dev/null
+++ b/sop-support/sop-service-support/src/main/java/com/gitee/sop/support/doc/helper/ParamsBuildHelper.java
@@ -0,0 +1,962 @@
+/*
+ * smart-doc https://github.com/smart-doc-group/smart-doc
+ *
+ * Copyright (C) 2018-2024 smart-doc
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.gitee.sop.support.doc.helper;
+
+import com.ly.doc.builder.ProjectDocConfigBuilder;
+import com.ly.doc.constants.DocGlobalConstants;
+import com.ly.doc.constants.DocTags;
+import com.ly.doc.constants.JavaTypeConstants;
+import com.ly.doc.constants.ParamTypeConstants;
+import com.ly.doc.extension.json.PropertyNameHelper;
+import com.ly.doc.extension.json.PropertyNamingStrategies;
+import com.ly.doc.model.ApiConfig;
+import com.ly.doc.model.ApiDataDictionary;
+import com.ly.doc.model.ApiParam;
+import com.ly.doc.model.CustomField;
+import com.ly.doc.model.CustomFieldInfo;
+import com.ly.doc.model.DocJavaField;
+import com.ly.doc.model.FieldJsonAnnotationInfo;
+import com.ly.doc.model.torna.EnumInfoAndValues;
+import com.ly.doc.utils.DocClassUtil;
+import com.ly.doc.utils.DocUtil;
+import com.ly.doc.utils.JavaClassUtil;
+import com.ly.doc.utils.JavaClassValidateUtil;
+import com.ly.doc.utils.JavaFieldUtil;
+import com.ly.doc.utils.ParamUtil;
+import com.power.common.model.EnumDictionary;
+import com.power.common.util.StringUtil;
+import com.thoughtworks.qdox.model.JavaAnnotation;
+import com.thoughtworks.qdox.model.JavaClass;
+import com.thoughtworks.qdox.model.JavaField;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * ApiParam Builder {@link ApiParam }
+ *
+ * @author yu 2019/12/21.
+ */
+public class ParamsBuildHelper extends BaseHelper {
+
+ /**
+ * Builds a parameter list based on field information.
+ *
+ * @param className The name of the generic type.
+ * @param pre A prefix builder for nested fields.
+ * @param level The next level of nesting.
+ * @param isRequired Indicates whether the parameter is required.
+ * @param isResp Indicates whether the parameter is a response parameter.
+ * @param registryClasses A collection of registered classes.
+ * @param projectBuilder A project builder instance.
+ * @param groupClasses A collection of JSR303 grouped classes.
+ * @param methodJsonViewClasses A set of valid `@JsonView` classes on controller
+ * method.
+ * @param pid The parent ID of the field.
+ * @param jsonRequest The JSON request object.
+ * @param atomicInteger An AtomicInteger for ID generation.
+ *
+ * This method handles various types of fields and their values, including handling
+ * self-referential loops, maps, arrays, objects, and primitive types. It adds
+ * parameters to the paramList based on the type and structure of the given field,
+ * recursively calling itself for nested or complex types.
+ * @return A List of ApiParam instances representing the built parameters.
+ */
+ public List buildParams(String className, String pre, int level, String isRequired, boolean isResp,
+ Map registryClasses, ProjectDocConfigBuilder projectBuilder, Set groupClasses,
+ Set methodJsonViewClasses, int pid, boolean jsonRequest, AtomicInteger atomicInteger) {
+
+ if (StringUtil.isEmpty(className)) {
+ throw new RuntimeException("Class name can't be null or empty.");
+ }
+
+ // Recursion limit check cached for efficiency
+ ApiConfig apiConfig = projectBuilder.getApiConfig();
+ int recursionLimit = apiConfig.getRecursionLimit();
+ if (level > recursionLimit) {
+ return Collections.emptyList();
+ }
+
+ int nextLevel = level + 1;
+ // Check circular reference
+ if (registryClasses.containsKey(className) && level > registryClasses.size()) {
+ return Collections.emptyList();
+ }
+
+ // Registry class
+ registryClasses.put(className, className);
+ String simpleName = DocClassUtil.getSimpleName(className);
+ String[] globGicName = DocClassUtil.getSimpleGicName(className);
+
+ if (Objects.isNull(globGicName) || globGicName.length < 1) {
+ JavaClass cls = projectBuilder.getClassByName(simpleName);
+ // obtain generics from parent class
+ JavaClass superJavaClass = Objects.nonNull(cls) ? cls.getSuperJavaClass() : null;
+ if (Objects.nonNull(superJavaClass)
+ && !JavaTypeConstants.OBJECT_SIMPLE_NAME.equals(superJavaClass.getSimpleName())) {
+ globGicName = DocClassUtil.getSimpleGicName(superJavaClass.getGenericFullyQualifiedName());
+ }
+ }
+
+ boolean isShowJavaType = apiConfig.getShowJavaType();
+
+ // if is primitive
+ if (JavaClassValidateUtil.isPrimitive(simpleName)) {
+ return handlePrimitiveType(simpleName, isShowJavaType, atomicInteger, pid);
+ }
+
+ // Handle collection types
+ if (JavaClassValidateUtil.isCollection(simpleName) || JavaClassValidateUtil.isArray(simpleName)) {
+ return handleCollectionOrArrayType(globGicName, pre, level, isRequired, isResp, registryClasses,
+ projectBuilder, groupClasses, methodJsonViewClasses, pid, jsonRequest, atomicInteger, simpleName);
+ }
+
+ // Handle map types
+ if (JavaClassValidateUtil.isMap(simpleName)) {
+ return buildMapParam(globGicName, pre, level, isRequired, isResp, registryClasses, projectBuilder,
+ groupClasses, methodJsonViewClasses, pid, jsonRequest, nextLevel, atomicInteger);
+ }
+
+ // Handle generic object types
+ if (JavaTypeConstants.JAVA_OBJECT_FULLY.equals(className)) {
+ return buildGenericObjectParam(className, pre, isRequired, atomicInteger, pid);
+ }
+
+ // Handle Reactor types
+ if (JavaClassValidateUtil.isReactor(simpleName)) {
+ if (globGicName.length > 0) {
+ return buildParams(globGicName[0], pre, nextLevel, isRequired, isResp, registryClasses, projectBuilder,
+ groupClasses, methodJsonViewClasses, pid, jsonRequest, atomicInteger);
+ }
+ return Collections.emptyList();
+ }
+
+ // handle Class Field
+ return processFields(className, pre, level, isRequired, isResp, registryClasses, projectBuilder, groupClasses,
+ methodJsonViewClasses, pid, jsonRequest, atomicInteger);
+ }
+
+ /**
+ * Processes fields of a given class and populates a list of API parameters based on
+ * the field types and properties.
+ *
+ * @param className The name of the class containing the fields.
+ * @param pre A prefix to prepend to field names.
+ * @param level The current level of nested fields.
+ * @param isRequired Indicates if the field is required.
+ * @param isResp Indicates if the field is part of a response.
+ * @param registryClasses A map of registry classes used for type resolution.
+ * @param projectBuilder The project builder used to access project-specific details.
+ * @param groupClasses A set of group classes relevant to the field processing.
+ * @param methodJsonViewClasses A set of JSON view classes applicable to methods.
+ * @param pid The parent ID of the current field.
+ * @param jsonRequest Indicates if the field is part of a JSON request.
+ * @param atomicInteger An AtomicInteger used for generating unique IDs.
+ * @return A list of API parameters representing the processed fields.
+ */
+ public List processFields(String className, String pre, int level, String isRequired,
+ boolean isResp, Map registryClasses, ProjectDocConfigBuilder projectBuilder,
+ Set groupClasses, Set methodJsonViewClasses, int pid, boolean jsonRequest,
+ AtomicInteger atomicInteger) {
+
+ if (StringUtil.isEmpty(className)) {
+ throw new RuntimeException("Class name can't be null or empty.");
+ }
+
+ // Check for recursion limit to avoid infinite loops
+ int recursionLimit = projectBuilder.getApiConfig().getRecursionLimit();
+
+ // Early exit when recursion limit is hit
+ if (level > recursionLimit) {
+ return Collections.emptyList();
+ }
+
+ // Avoid processing the same class multiple times
+ if (registryClasses.containsKey(className) && level > registryClasses.size()) {
+ return Collections.emptyList();
+ }
+
+ List paramList = new ArrayList<>();
+ String simpleName = DocClassUtil.getSimpleName(className);
+
+ JavaClass cls = projectBuilder.getClassByName(simpleName);
+ boolean isShowJavaType = projectBuilder.getApiConfig().getShowJavaType();
+ boolean requestFieldToUnderline = projectBuilder.getApiConfig().isRequestFieldToUnderline();
+ boolean responseFieldToUnderline = projectBuilder.getApiConfig().isResponseFieldToUnderline();
+ boolean displayActualType = projectBuilder.getApiConfig().isDisplayActualType();
+ ClassLoader classLoader = projectBuilder.getApiConfig().getClassLoader();
+
+ PropertyNamingStrategies.NamingBase fieldNameConvert = null;
+ // ignore
+ if (Objects.nonNull(cls)) {
+ List clsAnnotation = cls.getAnnotations();
+ fieldNameConvert = PropertyNameHelper.translate(clsAnnotation);
+ }
+
+ String[] globGicName = DocClassUtil.getSimpleGicName(className);
+ Map genericMap = new HashMap<>(globGicName.length);
+ JavaClassUtil.genericParamMap(genericMap, cls, globGicName);
+
+ Map ignoreFields = JavaClassUtil.getClassJsonIgnoreFields(cls);
+ List fields = JavaClassUtil.getFields(cls, 0, new LinkedHashMap<>(), classLoader);
+ for (DocJavaField docField : fields) {
+ JavaField field = docField.getJavaField();
+ // ignore transient field
+ if (isTransientField(field, projectBuilder, isResp)) {
+ continue;
+ }
+
+ String maxLength = JavaFieldUtil.getParamMaxLength(field.getAnnotations());
+ StringBuilder comment = new StringBuilder();
+ comment.append(docField.getComment());
+
+ String fieldName = docField.getFieldName();
+ if (Objects.nonNull(fieldNameConvert)) {
+ fieldName = fieldNameConvert.translate(fieldName);
+ }
+ if (ignoreFields.containsKey(fieldName)) {
+ continue;
+ }
+
+ String subTypeName = docField.getTypeFullyQualifiedName();
+ boolean needToUnderline = (responseFieldToUnderline && isResp) || (requestFieldToUnderline && !isResp);
+ if (needToUnderline) {
+ fieldName = StringUtil.camelToUnderline(fieldName);
+ }
+ String typeSimpleName = field.getType().getSimpleName();
+ String fieldGicName = docField.getTypeGenericCanonicalName();
+ List javaAnnotations = docField.getAnnotations();
+
+ Map tagsMap = DocUtil.getFieldTagsValue(field, docField);
+ // since tag value
+ String since = DocGlobalConstants.DEFAULT_VERSION;
+
+ if (tagsMap.containsKey(DocTags.SINCE)) {
+ since = tagsMap.get(DocTags.SINCE);
+ }
+ // handle extension
+ Map extensions = DocUtil.getCommentsByTag(field.getTagsByName(DocTags.EXTENSION),
+ DocTags.EXTENSION);
+ Map extensionParams = new HashMap<>(extensions.size());
+ if (!extensions.isEmpty()) {
+ extensions.forEach((k, v) -> extensionParams.put(k, DocUtil.detectTagValue(v)));
+ }
+
+ boolean strRequired = false;
+ CustomField.Key key = CustomField.Key.create(docField.getDeclaringClassName(), fieldName);
+
+ CustomField customResponseField = CustomField.nameEquals(key, projectBuilder.getCustomRespFieldMap());
+ CustomField customRequestField = CustomField.nameEquals(key, projectBuilder.getCustomReqFieldMap());
+
+ CustomFieldInfo customFieldInfo = getCustomFieldInfo(projectBuilder, docField, customResponseField,
+ customRequestField, isResp, simpleName);
+ // ignore custom field
+ if (Boolean.TRUE.equals(customFieldInfo.getIgnore())) {
+ continue;
+ }
+
+ // field json annotation
+ FieldJsonAnnotationInfo annotationInfo = getFieldJsonAnnotationInfo(projectBuilder, docField, isResp,
+ groupClasses, methodJsonViewClasses);
+ if (Boolean.TRUE.equals(annotationInfo.getIgnore())) {
+ continue;
+ }
+ // the param type from @JsonFormat
+ String fieldJsonFormatType = annotationInfo.getFieldJsonFormatType();
+ // the param value from @JsonFormat
+ String fieldJsonFormatValue = annotationInfo.getFieldJsonFormatValue();
+ // has Annotation @JsonSerialize And using ToStringSerializer
+ boolean toStringSerializer = Boolean.TRUE.equals(annotationInfo.getToStringSerializer());
+ if (Objects.nonNull(annotationInfo.getFieldName())) {
+ fieldName = annotationInfo.getFieldName();
+ }
+ if (Objects.nonNull(annotationInfo.getStrRequired())) {
+ strRequired = annotationInfo.getStrRequired();
+ }
+
+ for (JavaAnnotation annotation : field.getAnnotations()) {
+ if (JavaClassValidateUtil.isJSR303Required(annotation.getType().getValue())) {
+ strRequired = true;
+ break;
+ }
+ }
+
+ comment.append(JavaFieldUtil.getJsrComment(projectBuilder.getApiConfig().isShowValidation(), classLoader,
+ javaAnnotations));
+ // fix mock post form curl example error
+ String fieldValue = getFieldValueFromMock(tagsMap);
+
+ if (StringUtil.isNotEmpty(customFieldInfo.getFieldValue())) {
+ fieldValue = customFieldInfo.getFieldValue();
+ }
+ if (StringUtil.isNotEmpty(customFieldInfo.getFieldName())) {
+ fieldName = customFieldInfo.getFieldName();
+ }
+ if (StringUtil.isNotEmpty(customFieldInfo.getComment())) {
+ comment = new StringBuilder(customFieldInfo.getComment());
+ }
+ if (Objects.nonNull(customFieldInfo.getStrRequired())) {
+ strRequired = customFieldInfo.getStrRequired();
+ }
+
+ fieldName = fieldName.trim();
+
+ int nextLevel = level + 1;
+ // Analyzing File Type Field
+ if (JavaClassValidateUtil.isFile(fieldGicName)) {
+ ApiParam param = ApiParam.of()
+ .setField(pre + fieldName)
+ .setType(ParamTypeConstants.PARAM_TYPE_FILE)
+ .setClassName(className)
+ .setPid(pid)
+ .setId(atomicOrDefault(atomicInteger, paramList.size() + pid + 1))
+ .setMaxLength(maxLength)
+ .setDesc(comment.toString())
+ .setRequired(strRequired)
+ .setVersion(since)
+ .setExtensions(extensionParams);
+ if (fieldGicName.contains("[]") || fieldGicName.endsWith(">")) {
+ param.setType(ParamTypeConstants.PARAM_TYPE_FILE);
+ param.setDesc(comment.append("(array of file)").toString());
+ param.setHasItems(true);
+ }
+ paramList.add(param);
+ continue;
+ }
+ // Analyzing Map Type Field
+ if (JavaClassValidateUtil.isMap(subTypeName)) {
+ ApiParam param = ApiParam.of()
+ .setField(pre + fieldName)
+ .setType(ParamTypeConstants.PARAM_TYPE_OBJECT)
+ .setClassName(className)
+ .setPid(pid)
+ .setId(atomicOrDefault(atomicInteger, paramList.size() + pid + 1))
+ .setMaxLength(maxLength)
+ .setDesc(comment.toString())
+ .setRequired(strRequired)
+ .setVersion(since)
+ .setExtensions(extensionParams);
+ paramList.add(param);
+
+ List apiParams = buildMapParam(DocClassUtil.getSimpleGicName(fieldGicName),
+ DocUtil.getIndentByLevel(level), level + 1, isRequired, isResp, registryClasses, projectBuilder,
+ groupClasses, methodJsonViewClasses, param.getId(), jsonRequest, nextLevel, atomicInteger);
+ paramList.addAll(apiParams);
+ continue;
+ }
+ // Analyzing Primitive Type Field
+ if (JavaClassValidateUtil.isPrimitive(subTypeName)) {
+ if (StringUtil.isEmpty(fieldValue)) {
+ fieldValue = StringUtil.isNotEmpty(fieldJsonFormatValue) ? fieldJsonFormatValue : StringUtil
+ .removeQuotes(DocUtil.getValByTypeAndFieldName(typeSimpleName, field.getName()));
+ }
+
+ ApiParam param = ApiParam.of()
+ .setClassName(className)
+ .setField(pre + fieldName)
+ .setPid(pid)
+ .setMaxLength(maxLength)
+ .setValue(fieldValue);
+ param.setId(atomicOrDefault(atomicInteger, paramList.size() + param.getPid() + 1));
+ String processedType = (isResp && toStringSerializer) ? "string"
+ : StringUtil.isNotEmpty(fieldJsonFormatType) ? fieldJsonFormatType
+ : processFieldTypeName(isShowJavaType, subTypeName);
+ param.setType(processedType);
+ param.setExtensions(extensionParams);
+ // handle param
+ commonHandleParam(paramList, param, isRequired, comment.toString(), since, strRequired);
+
+ JavaClass enumClass = ParamUtil.handleSeeEnum(param, field, projectBuilder, isResp || jsonRequest,
+ tagsMap, fieldJsonFormatValue);
+ if (Objects.nonNull(enumClass)) {
+ String enumClassComment = DocGlobalConstants.EMPTY;
+ if (StringUtil.isNotEmpty(enumClass.getComment())) {
+ enumClassComment = enumClass.getComment();
+ }
+ comment = new StringBuilder(
+ StringUtils.isEmpty(comment.toString()) ? enumClassComment : comment.toString());
+ String enumComment = handleEnumComment(enumClass, projectBuilder);
+ param.setDesc(comment + enumComment);
+ }
+ } else {
+ String appendComment = "";
+ if (displayActualType) {
+ if (globGicName.length > 0) {
+ String gicName = genericMap.get(subTypeName) != null ? genericMap.get(subTypeName)
+ : globGicName[0];
+ if (!simpleName.equals(gicName)) {
+ appendComment = " (ActualType: " + JavaClassUtil.getClassSimpleName(gicName) + ")";
+ }
+ }
+ if (Objects.nonNull(docField.getActualJavaType())) {
+ appendComment = " (ActualType: "
+ + JavaClassUtil.getClassSimpleName(docField.getActualJavaType()) + ")";
+ }
+ }
+
+ StringBuilder preBuilder = DocUtil.getStringBuilderByLevel(level);
+ int fieldPid;
+ ApiParam param = ApiParam.of()
+ .setField(pre + fieldName)
+ .setClassName(className)
+ .setPid(pid)
+ .setMaxLength(maxLength);
+ param.setId(atomicOrDefault(atomicInteger, paramList.size() + param.getPid() + 1));
+ param.setExtensions(extensionParams);
+ String processedType;
+ if (fieldGicName.length() == 1) {
+ String gicName = JavaTypeConstants.JAVA_OBJECT_FULLY;
+ if (Objects.nonNull(genericMap.get(typeSimpleName))) {
+ gicName = genericMap.get(subTypeName);
+ } else {
+ if (globGicName.length > 0) {
+ gicName = globGicName[0];
+ }
+ }
+ if (JavaClassValidateUtil.isPrimitive(gicName)) {
+ processedType = DocClassUtil.processTypeNameForParams(gicName);
+ } else {
+ processedType = DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
+ }
+ } else {
+ processedType = StringUtil.isNotEmpty(fieldJsonFormatType) ? fieldJsonFormatType
+ : processFieldTypeName(isShowJavaType, subTypeName);
+ }
+ param.setType(processedType);
+ JavaClass javaClass = field.getType();
+ if (javaClass.isEnum()) {
+ comment.append(handleEnumComment(javaClass, projectBuilder));
+ ParamUtil.handleSeeEnum(param, field, projectBuilder, isResp || jsonRequest, tagsMap,
+ fieldJsonFormatValue);
+ // hand Param
+ commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
+ } else if (JavaClassValidateUtil.isCollection(subTypeName)
+ || JavaClassValidateUtil.isArray(subTypeName)) {
+ if (isShowJavaType) {
+ // rpc
+ param.setType(
+ JavaFieldUtil.convertToSimpleTypeName(docField.getTypeGenericFullyQualifiedName()));
+ } else {
+ param.setType(ParamTypeConstants.PARAM_TYPE_ARRAY);
+ }
+ if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
+ param.setValue(fieldValue);
+ }
+ if (globGicName.length > 0 && JavaTypeConstants.JAVA_LIST_FULLY.equals(fieldGicName)) {
+ // no generic, just object
+ fieldGicName = fieldGicName + "";
+ }
+ if (JavaClassValidateUtil.isArray(subTypeName)) {
+ fieldGicName = fieldGicName.substring(0, fieldGicName.lastIndexOf("["));
+ fieldGicName = "java.util.List<" + fieldGicName + ">";
+ }
+ String[] gNameArr = DocClassUtil.getSimpleGicName(fieldGicName);
+ if (gNameArr.length == 0) {
+ continue;
+ } else {
+ String gName = DocClassUtil.getSimpleGicName(fieldGicName)[0];
+ JavaClass javaClass1 = projectBuilder.getJavaProjectBuilder().getClassByName(gName);
+ comment.append(handleEnumComment(javaClass1, projectBuilder));
+ }
+ String gName = gNameArr[0];
+ if (JavaClassValidateUtil.isPrimitive(gName)) {
+ String builder = DocUtil.jsonValueByType(gName) + "," + DocUtil.jsonValueByType(gName);
+
+ if (StringUtil.isEmpty(fieldValue)) {
+ param.setValue(DocUtil.handleJsonStr(builder));
+ } else {
+ param.setValue(fieldValue);
+ }
+ commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
+ } else {
+ commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
+ fieldPid = Optional.ofNullable(atomicInteger).isPresent() ? param.getId()
+ : paramList.size() + pid;
+ if (!simpleName.equals(gName)) {
+ JavaClass arraySubClass = projectBuilder.getJavaProjectBuilder().getClassByName(gName);
+ if (arraySubClass.isEnum()) {
+ EnumInfoAndValues enumInfoAndValue = JavaClassUtil.getEnumInfoAndValue(arraySubClass,
+ projectBuilder, Boolean.FALSE);
+ if (Objects.nonNull(enumInfoAndValue)) {
+ param.setValue("[\"" + enumInfoAndValue.getValue() + "\"]")
+ .setEnumInfoAndValues(enumInfoAndValue)
+ .setType(enumInfoAndValue.getType());
+ }
+ } else if (gName.length() == 1) {
+ // handle generic
+ int len = globGicName.length;
+ if (len < 1) {
+ continue;
+ }
+ String gicName = genericMap.get(gName) != null ? genericMap.get(gName) : globGicName[0];
+
+ if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) {
+ paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
+ isResp, registryClasses, projectBuilder, groupClasses,
+ methodJsonViewClasses, fieldPid, jsonRequest, atomicInteger));
+ }
+ } else {
+ paramList.addAll(buildParams(gName, preBuilder.toString(), nextLevel, isRequired,
+ isResp, registryClasses, projectBuilder, groupClasses, methodJsonViewClasses,
+ fieldPid, jsonRequest, atomicInteger));
+ }
+ } else {
+ param.setSelfReferenceLoop(true);
+ }
+ }
+
+ } else if (JavaClassValidateUtil.isMap(subTypeName)) {
+ if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
+ param.setType(ParamTypeConstants.PARAM_TYPE_MAP);
+ param.setValue(fieldValue);
+ }
+ commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
+ fieldPid = Optional.ofNullable(atomicInteger).isPresent() ? param.getId() : paramList.size() + pid;
+ String valType = DocClassUtil.getMapKeyValueType(fieldGicName).length == 0 ? fieldGicName
+ : DocClassUtil.getMapKeyValueType(fieldGicName)[1];
+ if (JavaClassValidateUtil.isMap(fieldGicName)
+ || JavaTypeConstants.JAVA_OBJECT_FULLY.equals(valType)) {
+ ApiParam param1 = ApiParam.of()
+ .setField(preBuilder + "any object")
+ .setId(atomicOrDefault(atomicInteger, fieldPid + 1))
+ .setPid(fieldPid)
+ .setClassName(className)
+ .setMaxLength(maxLength)
+ .setType(ParamTypeConstants.PARAM_TYPE_OBJECT)
+ .setDesc(DocGlobalConstants.ANY_OBJECT_MSG)
+ .setVersion(DocGlobalConstants.DEFAULT_VERSION)
+ .setExtensions(extensionParams);
+ paramList.add(param1);
+ continue;
+ }
+ if (!JavaClassValidateUtil.isPrimitive(valType)) {
+ if (valType.length() == 1) {
+ String gicName = genericMap.get(valType);
+ if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) {
+ paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
+ isResp, registryClasses, projectBuilder, groupClasses, methodJsonViewClasses,
+ fieldPid, jsonRequest, atomicInteger));
+ }
+ } else {
+ paramList.addAll(buildParams(valType, preBuilder.toString(), nextLevel, isRequired, isResp,
+ registryClasses, projectBuilder, groupClasses, methodJsonViewClasses, fieldPid,
+ jsonRequest, atomicInteger));
+ }
+ }
+ } else if (JavaTypeConstants.JAVA_OBJECT_FULLY.equals(fieldGicName)) {
+ if (StringUtil.isEmpty(param.getDesc())) {
+ param.setDesc(DocGlobalConstants.ANY_OBJECT_MSG);
+ }
+ commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
+ } else if (fieldGicName.length() == 1) {
+ commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
+ fieldPid = Optional.ofNullable(atomicInteger).isPresent() ? param.getId() : paramList.size() + pid;
+ // handle java generic or object
+ if (!simpleName.equals(className)) {
+ if (globGicName.length > 0) {
+ String gicName = genericMap.get(subTypeName) != null ? genericMap.get(subTypeName)
+ : globGicName[0];
+ String simple = DocClassUtil.getSimpleName(gicName);
+ // set type array
+ if (JavaClassValidateUtil.isArray(gicName)) {
+ param.setType(ParamTypeConstants.PARAM_TYPE_ARRAY);
+ }
+ if (JavaClassValidateUtil.isPrimitive(simple)) {
+ // do nothing
+ } else if (gicName.contains("<")) {
+ if (JavaClassValidateUtil.isCollection(simple)) {
+ param.setType(ParamTypeConstants.PARAM_TYPE_ARRAY);
+ String gName = DocClassUtil.getSimpleGicName(gicName)[0];
+ if (!JavaClassValidateUtil.isPrimitive(gName)) {
+ paramList.addAll(buildParams(gName, preBuilder.toString(), nextLevel,
+ isRequired, isResp, registryClasses, projectBuilder, groupClasses,
+ methodJsonViewClasses, fieldPid, jsonRequest, atomicInteger));
+ }
+ } else {
+ paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
+ isResp, registryClasses, projectBuilder, groupClasses,
+ methodJsonViewClasses, fieldPid, jsonRequest, atomicInteger));
+ }
+ } else {
+ paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
+ isResp, registryClasses, projectBuilder, groupClasses, methodJsonViewClasses,
+ fieldPid, jsonRequest, atomicInteger));
+ }
+ } else {
+ paramList.addAll(buildParams(subTypeName, preBuilder.toString(), nextLevel, isRequired,
+ isResp, registryClasses, projectBuilder, groupClasses, methodJsonViewClasses,
+ fieldPid, jsonRequest, atomicInteger));
+ }
+ }
+ } else if (simpleName.equals(subTypeName)) {
+ // reference self
+ ApiParam param1 = ApiParam.of()
+ .setField(pre + fieldName)
+ .setPid(pid)
+ .setId(atomicOrDefault(atomicInteger, paramList.size() + pid + 1))
+ .setClassName(subTypeName)
+ .setMaxLength(maxLength)
+ .setType(ParamTypeConstants.PARAM_TYPE_OBJECT)
+ .setDesc(comment.append(" $ref... self").toString())
+ .setVersion(DocGlobalConstants.DEFAULT_VERSION)
+ .setExtensions(extensionParams);
+ paramList.add(param1);
+ } else {
+ commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
+ fieldGicName = DocUtil.formatFieldTypeGicName(genericMap, fieldGicName);
+ fieldPid = Optional.ofNullable(atomicInteger).isPresent() ? param.getId() : paramList.size() + pid;
+ paramList.addAll(buildParams(fieldGicName, preBuilder.toString(), nextLevel, isRequired, isResp,
+ registryClasses, projectBuilder, groupClasses, methodJsonViewClasses, fieldPid, jsonRequest,
+ atomicInteger));
+
+ }
+ }
+
+ }
+ return paramList;
+ // end field
+ }
+
+ /**
+ * Builds a list of {@link ApiParam} objects for a map parameter.
+ *
+ * @param globGicName the global generic name array
+ * @param pre the prefix string
+ * @param level the level of the parameter
+ * @param isRequired the requirement status of the parameter
+ * @param isResp the response flag
+ * @param registryClasses the map of registry classes
+ * @param projectBuilder the project configuration builder
+ * @param groupClasses the set of group classes
+ * @param jsonViewClasses A set of valid `@JsonView` classes.
+ * @param pid the parent ID
+ * @param jsonRequest the JSON request flag
+ * @param nextLevel the next level of the parameter
+ * @param atomicInteger the atomic integer for generating unique IDs
+ * @return a list of {@link ApiParam} objects
+ */
+ public List buildMapParam(String[] globGicName, String pre, int level, String isRequired,
+ boolean isResp, Map registryClasses, ProjectDocConfigBuilder projectBuilder,
+ Set groupClasses, Set jsonViewClasses, int pid, boolean jsonRequest, int nextLevel,
+ AtomicInteger atomicInteger) {
+ if (globGicName.length != 2) {
+ return Collections.emptyList();
+ }
+
+ // mock map key param
+ String mapKeySimpleName = DocClassUtil.getSimpleName(globGicName[0]);
+ String valueSimpleName = DocClassUtil.getSimpleName(globGicName[1]);
+ // get map key class
+ JavaClass mapKeyClass = projectBuilder.getJavaProjectBuilder().getClassByName(mapKeySimpleName);
+
+ boolean isShowJavaType = projectBuilder.getApiConfig().getShowJavaType();
+ String valueSimpleNameType = processFieldTypeName(isShowJavaType, valueSimpleName);
+ List paramList = new ArrayList<>();
+ // map key is enum
+ if (Objects.nonNull(mapKeyClass) && mapKeyClass.isEnum() && !mapKeyClass.getEnumConstants().isEmpty()) {
+ Integer keyParentId = null;
+ for (JavaField enumConstant : mapKeyClass.getEnumConstants()) {
+ ApiParam apiParam = ApiParam.of()
+ .setField(pre + enumConstant.getName())
+ .setType(valueSimpleNameType)
+ .setClassName(valueSimpleName)
+ .setDesc(StringUtil.isEmpty(enumConstant.getComment()) ? enumConstant.getName()
+ : enumConstant.getComment() + " "
+ + Optional.ofNullable(projectBuilder.getClassByName(valueSimpleName))
+ .map(JavaClass::getComment)
+ .orElse(DocGlobalConstants.DEFAULT_MAP_KEY_DESC))
+ .setVersion(DocGlobalConstants.DEFAULT_VERSION)
+ .setPid(null == keyParentId ? pid : keyParentId);
+ apiParam.setId(apiParam.getPid() + paramList.size() + 1);
+ if (null == keyParentId) {
+ keyParentId = apiParam.getPid();
+ }
+ paramList.add(apiParam);
+ // in foreach, need remove enum class in registry
+ registryClasses.remove(valueSimpleName);
+ List apiParams = addValueParams(valueSimpleName, globGicName, level, isRequired, isResp,
+ registryClasses, projectBuilder, groupClasses, jsonViewClasses, apiParam.getId(), jsonRequest,
+ nextLevel, atomicInteger);
+ paramList.addAll(apiParams);
+ }
+ return paramList;
+ }
+ // map key is primitive
+ if (JavaClassValidateUtil.isPrimitive(mapKeySimpleName)) {
+ ApiParam apiParam = ApiParam.of()
+ .setField(pre + "mapKey")
+ .setType(valueSimpleNameType)
+ .setClassName(valueSimpleName)
+ .setDesc(Optional.ofNullable(projectBuilder.getClassByName(valueSimpleName))
+ .map(JavaClass::getComment)
+ .orElse(DocGlobalConstants.DEFAULT_MAP_KEY_DESC))
+ .setVersion(DocGlobalConstants.DEFAULT_VERSION)
+ .setPid(pid)
+ .setId(atomicOrDefault(atomicInteger, ++pid));
+ paramList.add(apiParam);
+ }
+
+ paramList.addAll(addValueParams(valueSimpleName, globGicName, level, isRequired, isResp, registryClasses,
+ projectBuilder, groupClasses, jsonViewClasses, pid, jsonRequest, nextLevel, atomicInteger));
+ return paramList;
+ }
+
+ /**
+ * Adds parameters for the map value to the parameter list.
+ *
+ * @param valueSimpleName the simple name of the value type
+ * @param globGicName the global generic name array
+ * @param level the level of the parameter
+ * @param isRequired the requirement status of the parameter
+ * @param isResp the response flag
+ * @param registryClasses the map of registry classes
+ * @param projectBuilder the project configuration builder
+ * @param groupClasses the set of group classes
+ * @param jsonViewClasses A set of valid `@JsonView` classes.
+ * @param pid the parent ID
+ * @param jsonRequest the JSON request flag
+ * @param nextLevel the next level of the parameter
+ * @param atomicInteger the atomic integer for generating unique IDs
+ * @return the list of {@link ApiParam} objects
+ */
+ public List addValueParams(String valueSimpleName, String[] globGicName, int level,
+ String isRequired, boolean isResp, Map registryClasses,
+ ProjectDocConfigBuilder projectBuilder, Set groupClasses, Set jsonViewClasses, int pid,
+ boolean jsonRequest, int nextLevel, AtomicInteger atomicInteger) {
+ // build param when map value is not primitive
+ if (JavaClassValidateUtil.isPrimitive(valueSimpleName)) {
+ return Collections.emptyList();
+ }
+ return buildParams(globGicName[1], DocUtil.getIndentByLevel(level), nextLevel, isRequired, isResp,
+ registryClasses, projectBuilder, groupClasses, jsonViewClasses, pid, jsonRequest, atomicInteger);
+ }
+
+ public String dictionaryListComment(List enumDataDict) {
+ return enumDataDict.stream()
+ .map(apiDataDictionary -> apiDataDictionary.getName() + "-(\"" + apiDataDictionary.getValue() + "\",\""
+ + apiDataDictionary.getDesc() + "\")")
+ .collect(Collectors.joining(","));
+ }
+
+ public List primitiveReturnRespComment(String typeName, AtomicInteger atomicInteger, int pid) {
+ String comments = "Return " + typeName + ".";
+ ApiParam apiParam = ApiParam.of()
+ .setClassName(typeName)
+ .setId(atomicOrDefault(atomicInteger, pid + 1))
+ .setField("-")
+ .setPid(pid)
+ .setType(typeName)
+ .setDesc(comments)
+ .setVersion(DocGlobalConstants.DEFAULT_VERSION);
+
+ List paramList = new ArrayList<>();
+ paramList.add(apiParam);
+ return paramList;
+ }
+
+ public void commonHandleParam(List paramList, ApiParam param, String isRequired, String comment,
+ String since, boolean strRequired) {
+ if (StringUtil.isEmpty(isRequired)) {
+ param.setDesc(comment).setVersion(since);
+ } else {
+ param.setDesc(comment).setVersion(since).setRequired(strRequired);
+ }
+ paramList.add(param);
+ }
+
+ /**
+ * Handles the generation of comments for enum types in a Java class. If the class is
+ * an enum, it generates the corresponding enum comment based on the project
+ * configuration; otherwise, it returns an empty comment string.
+ *
+ * @param javaClass The JavaClass object containing class information.
+ * @param projectBuilder The ProjectDocConfigBuilder object containing project
+ * configuration information.
+ * @return The generated enum comment string.
+ */
+ public String handleEnumComment(JavaClass javaClass, ProjectDocConfigBuilder projectBuilder) {
+ String comment = "";
+ if (!javaClass.isEnum()) {
+ return comment;
+ }
+ String enumComments = javaClass.getComment();
+ if (Boolean.TRUE.equals(projectBuilder.getApiConfig().getInlineEnum())) {
+ ApiDataDictionary dataDictionary = projectBuilder.getApiConfig()
+ .getDataDictionary(javaClass.getCanonicalName());
+ if (Objects.isNull(dataDictionary)) {
+ // the output format should be unified ( as same as the "else" output)
+ comment = comment + "
[Enum: " + JavaClassUtil.getEnumParams(javaClass) + "]";
+ } else {
+ Class> enumClass = dataDictionary.getEnumClass();
+ if (enumClass.isInterface()) {
+ ClassLoader classLoader = projectBuilder.getApiConfig().getClassLoader();
+ try {
+ enumClass = classLoader.loadClass(javaClass.getFullyQualifiedName());
+ } catch (ClassNotFoundException e) {
+ return comment;
+ }
+ }
+ comment = comment + "
[Enum: " + dictionaryListComment(dataDictionary.getEnumDataDict(enumClass))
+ + "]";
+ }
+ } else {
+ if (StringUtil.isNotEmpty(enumComments)) {
+ comment = comment + "
(See: " + enumComments + ")";
+ }
+ comment = StringUtil.removeQuotes(comment);
+ }
+ return comment;
+ }
+
+ /**
+ * Returns the next value of the specified atomic integer or the default value if the
+ * atomic integer is null.
+ *
+ * @param atomicInteger the atomic integer
+ * @param defaultVal the default value
+ * @return the next value of the atomic integer or the default value
+ */
+ public int atomicOrDefault(AtomicInteger atomicInteger, int defaultVal) {
+ if (null != atomicInteger) {
+ return atomicInteger.incrementAndGet();
+ }
+ return defaultVal;
+ }
+
+ /**
+ * Processes the field type name based on the specified flag.
+ *
+ * @param isShowJavaType a flag indicating whether to show the Java type or not
+ * @param fieldTypeName the field type name to be processed
+ * @return the processed field type name
+ */
+ public String processFieldTypeName(boolean isShowJavaType, String fieldTypeName) {
+ if (isShowJavaType) {
+ return JavaFieldUtil.convertToSimpleTypeName(fieldTypeName);
+ } else {
+ return DocClassUtil.processTypeNameForParams(fieldTypeName.toLowerCase());
+ }
+ }
+
+ /**
+ * Handles primitive types and returns a list of {@link ApiParam} objects.
+ *
+ * @param simpleName the simple name of the primitive type
+ * @param isShowJavaType a flag indicating whether to show the Java type or not
+ * @param atomicInteger the atomic integer for generating unique IDs
+ * @param pid the parent ID
+ * @return the list of {@link ApiParam} objects
+ */
+ public List handlePrimitiveType(String simpleName, boolean isShowJavaType,
+ AtomicInteger atomicInteger, int pid) {
+ String processedType = processFieldTypeName(isShowJavaType, simpleName);
+ return primitiveReturnRespComment(processedType, atomicInteger, pid);
+ }
+
+ /**
+ * Builds a list of {@link ApiParam} objects for a map type.
+ *
+ * @param globGicName the generic canonical name of the map type
+ * @param pre the prefix for the field name
+ * @param level the level of the parameter
+ * @param isRequired the required flag for the parameter
+ * @param isResp the response flag for the parameter
+ * @param registryClasses the registry classes
+ * @param projectBuilder the project builder
+ * @param groupClasses the group classes
+ * @param methodJsonViewClasses the method JSON view classes
+ * @param pid the parent ID
+ * @param jsonRequest the request flag for the parameter
+ * @param atomicInteger the atomic integer for generating unique IDs
+ * @param simpleName the simple name of the collection type
+ */
+ public List handleCollectionOrArrayType(String[] globGicName, String pre, int level,
+ String isRequired, boolean isResp, Map registryClasses,
+ ProjectDocConfigBuilder projectBuilder, Set groupClasses, Set methodJsonViewClasses,
+ int pid, boolean jsonRequest, AtomicInteger atomicInteger, String simpleName) {
+ List paramList = new ArrayList<>();
+ if (!JavaClassValidateUtil.isCollection(globGicName[0])) {
+ String gNameTemp = globGicName[0];
+ String gName = JavaClassValidateUtil.isArray(gNameTemp) ? gNameTemp.substring(0, gNameTemp.indexOf("["))
+ : globGicName[0];
+ if (JavaClassValidateUtil.isPrimitive(gName)) {
+ String processedType = projectBuilder.getApiConfig().getShowJavaType()
+ ? JavaFieldUtil.convertToSimpleTypeName(simpleName)
+ : DocClassUtil.processTypeNameForParams(gName);
+ ApiParam param = ApiParam.of()
+ .setId(atomicOrDefault(atomicInteger, pid + 1))
+ .setField(pre + " -")
+ .setType("array[" + processedType + "]")
+ .setPid(pid)
+ .setDesc("array of " + processedType)
+ .setVersion(DocGlobalConstants.DEFAULT_VERSION)
+ .setRequired(Boolean.parseBoolean(isRequired));
+ paramList.add(param);
+ } else {
+ if (JavaClassValidateUtil.isArray(gNameTemp)) {
+ gNameTemp = gNameTemp.substring(0, gNameTemp.indexOf("["));
+ }
+ paramList.addAll(buildParams(gNameTemp, pre, level + 1, isRequired, isResp, registryClasses,
+ projectBuilder, groupClasses, methodJsonViewClasses, pid, jsonRequest, atomicInteger));
+ }
+ }
+ return paramList;
+ }
+
+ /**
+ * Builds a list of {@link ApiParam} objects for a generic object type.
+ *
+ * @param className the canonical name of the generic object type
+ * @param pre the prefix for the field name
+ * @param isRequired the required flag for the parameter
+ * @param atomicInteger the atomic integer for generating unique IDs
+ * @param pid the parent ID
+ * @return the list of {@link ApiParam} objects
+ */
+ public List buildGenericObjectParam(String className, String pre, String isRequired,
+ AtomicInteger atomicInteger, int pid) {
+ List paramList = new ArrayList<>();
+ ApiParam apiParam = ApiParam.of()
+ .setClassName(className)
+ .setId(atomicOrDefault(atomicInteger, pid + 1))
+ .setField(pre + "any object")
+ .setType(ParamTypeConstants.PARAM_TYPE_OBJECT)
+ .setPid(pid)
+ .setDesc(DocGlobalConstants.ANY_OBJECT_MSG)
+ .setVersion(DocGlobalConstants.DEFAULT_VERSION)
+ .setRequired(Boolean.parseBoolean(isRequired));
+ paramList.add(apiParam);
+ return paramList;
+ }
+
+}
diff --git a/sop-support/sop-service-support/src/main/resources/META-INF/services/com.ly.doc.template.IDocBuildTemplate b/sop-support/sop-service-support/src/main/resources/META-INF/services/com.ly.doc.template.IDocBuildTemplate
new file mode 100644
index 00000000..2f27426a
--- /dev/null
+++ b/sop-support/sop-service-support/src/main/resources/META-INF/services/com.ly.doc.template.IDocBuildTemplate
@@ -0,0 +1 @@
+com.gitee.sop.support.doc.SopDocBuildTemplate
diff --git a/sop-website/sop-website-frontend/mock/asyncRoutes.ts b/sop-website/sop-website-frontend/mock/asyncRoutes.ts
index d95d20cf..5305f416 100755
--- a/sop-website/sop-website-frontend/mock/asyncRoutes.ts
+++ b/sop-website/sop-website-frontend/mock/asyncRoutes.ts
@@ -28,6 +28,14 @@ const permissionRouter = {
title: "签名算法",
showLink: false
}
+ },
+ {
+ path: "/doc/code",
+ name: "DocCode",
+ meta: {
+ title: "公共错误码",
+ showLink: false
+ }
}
]
};
diff --git a/sop-website/sop-website-frontend/public/static/code.json b/sop-website/sop-website-frontend/public/static/code.json
new file mode 100644
index 00000000..228ecf37
--- /dev/null
+++ b/sop-website/sop-website-frontend/public/static/code.json
@@ -0,0 +1,334 @@
+[
+ {
+ "children":[
+
+ ],
+ "code":"0",
+ "id":1,
+ "msg":"成功"
+ },
+ {
+ "children":[
+ {
+ "id":3,
+ "solution":"重新获取token",
+ "sub_code":"aop.invalid-auth-token",
+ "sub_msg":"无效的访问令牌"
+ },
+ {
+ "id":4,
+ "solution":"重新获取token",
+ "sub_code":"aop.auth-token-time-out",
+ "sub_msg":"访问令牌已过期"
+ },
+ {
+ "id":5,
+ "solution":"重新获取token",
+ "sub_code":"aop.invalid-app-auth-token",
+ "sub_msg":"无效的应用授权令牌"
+ },
+ {
+ "id":6,
+ "solution":"联系平台进行授权",
+ "sub_code":"aop.invalid-app-auth-token-no-api",
+ "sub_msg":"商户未授权当前接口"
+ },
+ {
+ "id":7,
+ "solution":"重新获取token",
+ "sub_code":"aop.app-auth-token-time-out",
+ "sub_msg":"应用授权令牌已过期"
+ },
+ {
+ "id":8,
+ "solution":"联系平台处理",
+ "sub_code":"aop.no-product-reg-by-partner",
+ "sub_msg":"商户未签约任何产品"
+ }
+ ],
+ "code":"20001",
+ "id":2,
+ "msg":"认证异常"
+ },
+ {
+ "children":[
+ {
+ "id":10,
+ "solution":"检查参数正确",
+ "sub_code":"isv.invalid-parameter",
+ "sub_msg":"参数无效"
+ },
+ {
+ "id":11,
+ "solution":"检查传参",
+ "sub_code":"isv.error-parameter",
+ "sub_msg":"参数不正确"
+ },
+ {
+ "id":12,
+ "solution":"检查上传文件",
+ "sub_code":"isv.upload-fail",
+ "sub_msg":"文件上传失败"
+ },
+ {
+ "id":13,
+ "solution":"检查文件后缀名",
+ "sub_code":"isv.invalid-file-extension",
+ "sub_msg":"文件扩展名无效"
+ },
+ {
+ "id":14,
+ "solution":"检查文档大小",
+ "sub_code":"isv.invalid-file-size",
+ "sub_msg":"{0}文件大小无效,单文件不得超过{1}"
+ },
+ {
+ "id":15,
+ "solution":"检查接口名称是否正确",
+ "sub_code":"isv.invalid-method",
+ "sub_msg":"不存在的方法名"
+ },
+ {
+ "id":16,
+ "solution":"检查format参数是否正确",
+ "sub_code":"isv.invalid-format",
+ "sub_msg":"无效的数据格式"
+ },
+ {
+ "id":17,
+ "solution":"检查sign_type是否正确",
+ "sub_code":"isv.invalid-signature-type",
+ "sub_msg":"无效的签名类型"
+ },
+ {
+ "id":18,
+ "solution":"检查签名结果是否正确",
+ "sub_code":"isv.invalid-signature",
+ "sub_msg":"无效签名"
+ },
+ {
+ "id":19,
+ "solution":"检查签名结果是否正确",
+ "sub_code":"isv.invalid-encrypt-type",
+ "sub_msg":"无效的加密类型"
+ },
+ {
+ "id":20,
+ "solution":"检查签名结果是否正确",
+ "sub_code":"isv.invalid-encrypt",
+ "sub_msg":"解密异常"
+ },
+ {
+ "id":21,
+ "solution":"检查appId是否正确",
+ "sub_code":"isv.invalid-app-id",
+ "sub_msg":"无效的 appId 参数"
+ },
+ {
+ "id":22,
+ "solution":"检查时间戳格式是否正确",
+ "sub_code":"isv.invalid-timestamp",
+ "sub_msg":"非法的时间戳参数"
+ },
+ {
+ "id":23,
+ "solution":"检查charset参数是否正确",
+ "sub_code":"isv.invalid-charset",
+ "sub_msg":"字符集错误"
+ },
+ {
+ "id":24,
+ "solution":"检查签名",
+ "sub_code":"isv.invalid-digest",
+ "sub_msg":"摘要错误"
+ },
+ {
+ "id":25,
+ "solution":"",
+ "sub_code":"isv.decryption-error-not-valid-encrypt-type",
+ "sub_msg":"解密出错,不支持的加密算法"
+ },
+ {
+ "id":26,
+ "solution":"",
+ "sub_code":"isv.decryption-error-not-valid-encrypt-key",
+ "sub_msg":"解密出错, 未配置加密密钥或加密密钥格式错误"
+ },
+ {
+ "id":27,
+ "solution":"",
+ "sub_code":"isv.decryption-error-unknown",
+ "sub_msg":"解密出错,未知异常"
+ },
+ {
+ "id":28,
+ "solution":"",
+ "sub_code":"isv.missing-signature-config",
+ "sub_msg":"验签出错, 未配置对应签名算法的公钥或者证书"
+ },
+ {
+ "id":29,
+ "solution":"",
+ "sub_code":"isv.not-support-app-auth",
+ "sub_msg":"本接口不支持第三方代理调用"
+ },
+ {
+ "id":30,
+ "solution":"",
+ "sub_code":"isv.suspected-attack",
+ "sub_msg":"可疑的攻击请求"
+ },
+ {
+ "id":31,
+ "solution":"",
+ "sub_code":"isv.invalid-content-type",
+ "sub_msg":"无效的 content-type"
+ }
+ ],
+ "code":"40002",
+ "id":9,
+ "msg":"错误参数"
+ },
+ {
+ "children":[
+ {
+ "id":33,
+ "solution":"检查接口名",
+ "sub_code":"isv.missing-method",
+ "sub_msg":"缺少方法名参数"
+ },
+ {
+ "id":34,
+ "solution":"检查签名sign参数",
+ "sub_code":"isv.missing-signature",
+ "sub_msg":"缺少签名参数"
+ },
+ {
+ "id":35,
+ "solution":"检查签名类型参数",
+ "sub_code":"isv.missing-signature-type",
+ "sub_msg":"缺少签名类型参数"
+ },
+ {
+ "id":36,
+ "solution":"",
+ "sub_code":"isv.missing-signature-key",
+ "sub_msg":"缺少签名配置"
+ },
+ {
+ "id":37,
+ "solution":"appId参数必填",
+ "sub_code":"isv.missing-app-id",
+ "sub_msg":"缺少 appId 参数"
+ },
+ {
+ "id":38,
+ "solution":"时间戳参数必填",
+ "sub_code":"isv.missing-timestamp",
+ "sub_msg":"缺少时间戳参数"
+ },
+ {
+ "id":39,
+ "solution":"版本号参数必填",
+ "sub_code":"isv.missing-version",
+ "sub_msg":"缺少版本参数"
+ },
+ {
+ "id":40,
+ "solution":"",
+ "sub_code":"isv.decryption-error-missing-encrypt-type",
+ "sub_msg":"解密出错, 未指定加密算法"
+ }
+ ],
+ "code":"40001",
+ "id":32,
+ "msg":"缺少参数"
+ },
+ {
+ "children":[
+ {
+ "id":42,
+ "solution":"网关异常",
+ "sub_code":"isp.unknown-error",
+ "sub_msg":"服务暂不可用"
+ },
+ {
+ "id":43,
+ "solution":"服务提供异常",
+ "sub_code":"isp.service-unknown-error",
+ "sub_msg":"服务不可用"
+ },
+ {
+ "id":44,
+ "solution":"服务不可用",
+ "sub_code":"isp.service-not-available",
+ "sub_msg":"服务暂不可用"
+ },
+ {
+ "id":45,
+ "solution":"联系平台排查日志",
+ "sub_code":"isp.gateway-response-timeout",
+ "sub_msg":"网关响应超时"
+ },
+ {
+ "id":46,
+ "solution":"联系平台排查日志",
+ "sub_code":"isv.service-busy",
+ "sub_msg":"服务器忙"
+ }
+ ],
+ "code":"99999",
+ "id":41,
+ "msg":"未知异常"
+ },
+ {
+ "children":[
+ {
+ "id":48,
+ "solution":"接口无权限,联系平台授权",
+ "sub_code":"isv.insufficient-isv-permissions",
+ "sub_msg":"请检查配置的账户是否有当前接口权限"
+ },
+ {
+ "id":49,
+ "solution":"联系平台授权",
+ "sub_code":"isv.insufficient-user-permissions",
+ "sub_msg":"代理的商户没有当前接口权限"
+ },
+ {
+ "id":50,
+ "solution":"联系平台授权",
+ "sub_code":"isv.route-no-permissions",
+ "sub_msg":"没有当前接口权限"
+ },
+ {
+ "id":51,
+ "solution":"访问首先",
+ "sub_code":"isv.access-forbidden",
+ "sub_msg":"无权访问"
+ },
+ {
+ "id":52,
+ "solution":"IP受限",
+ "sub_code":"isv.ip-forbidden",
+ "sub_msg":"IP无权访问"
+ }
+ ],
+ "code":"40006",
+ "id":47,
+ "msg":"权限异常"
+ },
+ {
+ "children":[
+ {
+ "id":54,
+ "solution":"",
+ "sub_code":"isp.biz-error",
+ "sub_msg":"业务异常"
+ }
+ ],
+ "code":"50003",
+ "id":53,
+ "msg":"业务异常"
+ }
+]
diff --git a/sop-website/sop-website-frontend/src/utils/http/index.ts b/sop-website/sop-website-frontend/src/utils/http/index.ts
index 1d63071e..91020554 100755
--- a/sop-website/sop-website-frontend/src/utils/http/index.ts
+++ b/sop-website/sop-website-frontend/src/utils/http/index.ts
@@ -224,7 +224,5 @@ export const http = new PureHttp();
* @param path 相对于public文件夹路径,如文件在public/static/sign.md,填:static/sign.md
*/
export function getFile(path) {
- return Axios.get(path, {
- responseType: "text"
- });
+ return Axios.get(path);
}
diff --git a/sop-website/sop-website-frontend/src/views/doc/api/index.vue b/sop-website/sop-website-frontend/src/views/doc/api/index.vue
index d878afd6..7670e9dd 100755
--- a/sop-website/sop-website-frontend/src/views/doc/api/index.vue
+++ b/sop-website/sop-website-frontend/src/views/doc/api/index.vue
@@ -138,7 +138,19 @@ const defaultProps = {
-
+
+
+
+ 网关返回码,详见
+
+ 公共错误码
+
+
+
+ {{ scope.row.description }}
+
+
+
业务返回参数
diff --git a/sop-website/sop-website-frontend/src/views/doc/code/index.vue b/sop-website/sop-website-frontend/src/views/doc/code/index.vue
new file mode 100644
index 00000000..10cdd45c
--- /dev/null
+++ b/sop-website/sop-website-frontend/src/views/doc/code/index.vue
@@ -0,0 +1,31 @@
+
+
+
+
公共错误码
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sop-website/sop-website-frontend/src/views/doc/sign/index.ts b/sop-website/sop-website-frontend/src/views/doc/sign/index.ts
deleted file mode 100755
index 379fd088..00000000
--- a/sop-website/sop-website-frontend/src/views/doc/sign/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { ref } from "vue";
-
-export const value = ref("");
diff --git a/sop-website/sop-website-frontend/src/views/doc/sign/index.vue b/sop-website/sop-website-frontend/src/views/doc/sign/index.vue
index 4ab8ce19..ee579370 100755
--- a/sop-website/sop-website-frontend/src/views/doc/sign/index.vue
+++ b/sop-website/sop-website-frontend/src/views/doc/sign/index.vue
@@ -1,10 +1,13 @@