From a2aec5c160ac962579ea8cacfc80dfd6eb071b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E4=BA=AE?= Date: Sun, 20 Oct 2024 23:31:57 +0800 Subject: [PATCH 1/3] add generate openapi logic --- .../dubbo/common/utils/StringUtils.java | 58 + .../dubbo/metadata/MetadataService.java | 3 + .../metadata/swagger/MethodAttributes.java | 346 +++ .../metadata/swagger/OpenAPIGenerator.java | 397 +++ .../metadata/swagger/OpenAPIService.java | 116 + .../metadata/swagger/ParameterService.java | 332 +++ .../metadata/swagger/RequestBodyService.java | 104 + .../metadata/swagger/RequestService.java | 229 ++ .../metadata/swagger/ResponseService.java | 367 +++ .../metadata/swagger/RouterOperation.java | 348 +++ .../metadata/swagger/SwaggerConstants.java | 51 + .../metadata/swagger/model/Components.java | 296 +++ .../dubbo/metadata/swagger/model/OpenAPI.java | 364 +++ .../metadata/swagger/model/Operation.java | 330 +++ .../swagger/model/OperationService.java | 87 + .../metadata/swagger/model/PathItem.java | 536 ++++ .../dubbo/metadata/swagger/model/Paths.java | 107 + .../metadata/swagger/model/SpecVersion.java | 22 + .../swagger/model/annotations/OpenAPI30.java | 22 + .../swagger/model/annotations/OpenAPI31.java | 22 + .../swagger/model/headers/Header.java | 300 +++ .../metadata/swagger/model/info/Info.java | 219 ++ .../swagger/model/media/ArraySchema.java | 48 + .../swagger/model/media/BinarySchema.java | 110 + .../swagger/model/media/BooleanSchema.java | 98 + .../swagger/model/media/ByteArraySchema.java | 110 + .../swagger/model/media/ComposedSchema.java | 32 + .../metadata/swagger/model/media/Content.java | 70 + .../swagger/model/media/DateSchema.java | 93 + .../swagger/model/media/DateTimeSchema.java | 102 + .../swagger/model/media/EmailSchema.java | 87 + .../swagger/model/media/FileSchema.java | 66 + .../swagger/model/media/IntegerSchema.java | 93 + .../swagger/model/media/JsonSchema.java | 38 + .../swagger/model/media/MapSchema.java | 60 + .../swagger/model/media/MediaType.java | 159 ++ .../swagger/model/media/NumberSchema.java | 88 + .../swagger/model/media/ObjectSchema.java | 75 + .../swagger/model/media/PasswordSchema.java | 87 + .../metadata/swagger/model/media/Schema.java | 2294 +++++++++++++++++ .../swagger/model/media/StringSchema.java | 87 + .../swagger/model/media/UUIDSchema.java | 101 + .../swagger/model/parameters/Parameter.java | 418 +++ .../swagger/model/parameters/ParameterId.java | 136 + .../model/parameters/ParameterInfo.java | 117 + .../swagger/model/parameters/RequestBody.java | 194 ++ .../model/parameters/RequestBodyInfo.java | 75 + .../swagger/model/responses/ApiResponse.java | 199 ++ .../swagger/model/responses/ApiResponses.java | 133 + .../swagger/model/servers/Server.java | 162 ++ .../swagger/model/servers/ServerVariable.java | 172 ++ .../model/servers/ServerVariables.java | 112 + .../metadata/swagger/model/tags/Tag.java | 141 + .../metadata/swagger/utils/PathUtils.java | 127 + .../metadata/swagger/utils/PrimitiveType.java | 458 ++++ .../swagger/utils/ReturnTypeParser.java | 25 + .../metadata/MetadataServiceDelegation.java | 30 + .../DefaultRequestMappingRegistry.java | 7 + .../tri/rest/mapping/RequestMapping.java | 12 + .../mapping/condition/ConsumesCondition.java | 12 + .../mapping/condition/HeadersCondition.java | 4 + .../mapping/condition/ParamsCondition.java | 5 + 62 files changed, 11093 insertions(+) create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/MethodAttributes.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIGenerator.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIService.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/ParameterService.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RequestBodyService.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RequestService.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/ResponseService.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RouterOperation.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/SwaggerConstants.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Components.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/OpenAPI.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Operation.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/OperationService.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/PathItem.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Paths.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/SpecVersion.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/annotations/OpenAPI30.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/annotations/OpenAPI31.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/headers/Header.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/info/Info.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ArraySchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/BinarySchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/BooleanSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ByteArraySchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ComposedSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/Content.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/DateSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/DateTimeSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/EmailSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/FileSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/IntegerSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/JsonSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/MapSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/MediaType.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/NumberSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ObjectSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/PasswordSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/Schema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/StringSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/UUIDSchema.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/Parameter.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/ParameterId.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/ParameterInfo.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/RequestBody.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/RequestBodyInfo.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/responses/ApiResponse.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/responses/ApiResponses.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/Server.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/ServerVariable.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/ServerVariables.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/tags/Tag.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PathUtils.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PrimitiveType.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/ReturnTypeParser.java diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java index 74786e8a2e1..6c6225e691d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java @@ -1362,4 +1362,62 @@ public static List tokenizeToList(String str, char... separators) { } return tokens; } + + public static String trimToNull(String substring) { + if (substring == null) { + return null; + } + String trimmed = substring.trim(); + return trimmed.isEmpty() ? null : trimmed; + } + + public static boolean contains(CharSequence seq, CharSequence searchSeq) { + return (seq != null && searchSeq != null) && indexOf(seq, searchSeq, 0) >= 0; + } + + private static int indexOf(CharSequence cs, CharSequence searchChar, int start) { + String searchString = searchChar.toString(); // 将 searchChar 转为 String + + if (cs instanceof String) { + return ((String) cs).indexOf(searchString, start); + } else if (cs instanceof StringBuilder) { + return ((StringBuilder) cs).indexOf(searchString, start); + } else if (cs instanceof StringBuffer) { + return ((StringBuffer) cs).indexOf(searchString, start); + } else { + return cs.toString().indexOf(searchString, start); + } + } + + public static boolean containsAny(CharSequence cs, CharSequence... searchCharSequences) { + return containsAny(StringUtils::contains, cs, searchCharSequences); + } + + private static boolean containsAny( + ToBooleanBiFunction test, + CharSequence cs, + CharSequence... searchCharSequences) { + + if (!isEmpty(cs) && searchCharSequences != null && searchCharSequences.length > 0) { + for (CharSequence searchCharSequence : searchCharSequences) { + if (test.applyAsBoolean(cs, searchCharSequence)) { + return true; + } + } + } + return false; + } + + private static boolean isEmpty(CharSequence cs) { + return cs == null || cs.length() == 0; + } + + public static String defaultIfEmpty(String str, String defaultStr) { + return isEmpty(str) ? defaultStr : str; + } + + @FunctionalInterface + private interface ToBooleanBiFunction { + boolean applyAsBoolean(T t, U u); + } } diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java index cd767adcad9..7f66ed7d579 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java @@ -17,6 +17,7 @@ package org.apache.dubbo.metadata; import org.apache.dubbo.common.URL; +import org.apache.dubbo.metadata.swagger.model.OpenAPI; import java.util.Collections; import java.util.List; @@ -226,4 +227,6 @@ static boolean isMetadataService(String interfaceName) { * @since 3.0 */ String getAndListenInstanceMetadata(String consumerId, InstanceMetadataChangedListener listener); + + OpenAPI getOpenAPI(); } diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/MethodAttributes.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/MethodAttributes.java new file mode 100644 index 00000000000..0ae8ebf72d7 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/MethodAttributes.java @@ -0,0 +1,346 @@ +/* + * 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 org.apache.dubbo.metadata.swagger; + +import org.apache.dubbo.common.lang.Nullable; +import org.apache.dubbo.metadata.swagger.model.responses.ApiResponse; +import org.apache.dubbo.metadata.swagger.model.responses.ApiResponses; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; + +public class MethodAttributes { + + /** + * The Default consumes media type. + */ + private final String defaultConsumesMediaType; + + /** + * The Default produces media type. + */ + private final String defaultProducesMediaType; + + /** + * The Headers. + */ + private final LinkedHashMap headers = new LinkedHashMap<>(); + + /** + * The Locale. + */ + private final Locale locale; + + /** + * The Method overloaded. + */ + private boolean methodOverloaded; + + /** + * The Class produces. + */ + private String[] classProduces; + + /** + * The Class consumes. + */ + private String[] classConsumes; + + /** + * The Method produces. + */ + private String[] methodProduces = {}; + + /** + * The Method consumes. + */ + private String[] methodConsumes = {}; + + /** + * The Generic map response. + */ + private Map genericMapResponse = new LinkedHashMap<>(); + + /** + * The Use return type schema. + */ + private boolean useReturnTypeSchema; + + /** + * Instantiates a new Method attributes. + * + * @param methodProducesNew the method produces new + * @param defaultConsumesMediaType the default consumes media type + * @param defaultProducesMediaType the default produces media type + * @param genericMapResponse the generic map response + * @param locale the locale + */ + public MethodAttributes( + String[] methodProducesNew, + String defaultConsumesMediaType, + String defaultProducesMediaType, + Map genericMapResponse, + Locale locale) { + this.methodProduces = methodProducesNew; + this.defaultConsumesMediaType = defaultConsumesMediaType; + this.defaultProducesMediaType = defaultProducesMediaType; + this.genericMapResponse = genericMapResponse; + this.locale = locale; + } + + /** + * Instantiates a new Method attributes. + * + * @param defaultConsumesMediaType the default consumes media type + * @param defaultProducesMediaType the default produces media type + * @param locale the locale + */ + public MethodAttributes(String defaultConsumesMediaType, String defaultProducesMediaType, Locale locale) { + this.defaultConsumesMediaType = defaultConsumesMediaType; + this.defaultProducesMediaType = defaultProducesMediaType; + this.locale = locale; + } + + /** + * Instantiates a new Method attributes. + * + * @param defaultConsumesMediaType the default consumes media type + * @param defaultProducesMediaType the default produces media type + * @param methodConsumes the method consumes + * @param methodProduces the method produces + * @param headers the headers + * @param locale the locale + */ + public MethodAttributes( + String defaultConsumesMediaType, + String defaultProducesMediaType, + String[] methodConsumes, + String[] methodProduces, + String[] headers, + Locale locale) { + this.defaultConsumesMediaType = defaultConsumesMediaType; + this.defaultProducesMediaType = defaultProducesMediaType; + this.methodProduces = methodProduces; + this.methodConsumes = methodConsumes; + this.locale = locale; + setHeaders(headers); + } + + /** + * Get class produces string [ ]. + * + * @return the string [ ] + */ + public String[] getClassProduces() { + return classProduces; + } + + /** + * Sets class produces. + * + * @param classProduces the class produces + */ + public void setClassProduces(String[] classProduces) { + this.classProduces = classProduces; + } + + /** + * Get class consumes string [ ]. + * + * @return the string [ ] + */ + public String[] getClassConsumes() { + return classConsumes; + } + + /** + * Sets class consumes. + * + * @param classConsumes the class consumes + */ + public void setClassConsumes(String[] classConsumes) { + this.classConsumes = classConsumes; + } + + /** + * Get method produces string [ ]. + * + * @return the string [ ] + */ + public String[] getMethodProduces() { + return methodProduces; + } + + /** + * Get method consumes string [ ]. + * + * @return the string [ ] + */ + public String[] getMethodConsumes() { + return methodConsumes; + } + + /** + * Fill methods. + * + * @param produces the produces + * @param consumes the consumes + * @param headers the headers + */ + private void fillMethods(String[] produces, String[] consumes, String[] headers) { + if (ArrayUtils.isNotEmpty(produces)) { + methodProduces = mergeArrays(methodProduces, produces); + } else if (ArrayUtils.isNotEmpty(classProduces)) { + methodProduces = mergeArrays(methodProduces, classProduces); + } else if (ArrayUtils.isEmpty(methodProduces)) { + methodProduces = new String[] {defaultProducesMediaType}; + } + + if (ArrayUtils.isNotEmpty(consumes)) { + methodConsumes = mergeArrays(methodConsumes, consumes); + } else if (ArrayUtils.isNotEmpty(classConsumes)) { + methodConsumes = mergeArrays(methodConsumes, classConsumes); + } else if (ArrayUtils.isEmpty(methodConsumes)) { + methodConsumes = new String[] {defaultConsumesMediaType}; + } + setHeaders(headers); + } + + /** + * Merge string arrays into one array with unique values + * + * @param array1 the array1 + * @param array2 the array2 + * @return the string [ ] + */ + private String[] mergeArrays(@Nullable String[] array1, String[] array2) { + Set uniqueValues = array1 == null + ? new LinkedHashSet<>() + : Arrays.stream(array1).collect(Collectors.toCollection(LinkedHashSet::new)); + uniqueValues.addAll(Arrays.asList(array2)); + return uniqueValues.toArray(new String[0]); + } + + /** + * Is method overloaded boolean. + * + * @return the boolean + */ + public boolean isMethodOverloaded() { + return methodOverloaded; + } + + /** + * Sets method overloaded. + * + * @param overloaded the overloaded + */ + public void setMethodOverloaded(boolean overloaded) { + methodOverloaded = overloaded; + } + + /** + * Gets headers. + * + * @return the headers + */ + public Map getHeaders() { + return headers; + } + + /** + * Sets headers. + * + * @param headers the headers + */ + private void setHeaders(String[] headers) { + if (ArrayUtils.isNotEmpty(headers)) + for (String header : headers) { + if (!header.contains("!=")) { + String[] keyValueHeader = header.split("="); + String headerValue = keyValueHeader.length > 1 ? keyValueHeader[1] : ""; + this.headers.put(keyValueHeader[0], headerValue); + } else { + String[] keyValueHeader = header.split("!="); + if (!this.headers.containsKey(keyValueHeader[0])) + this.headers.put(keyValueHeader[0], StringUtils.EMPTY); + } + } + } + + /** + * Calculate generic map response api responses. + * + * @param genericMapResponse the generic map response + * @return the api responses + */ + public ApiResponses calculateGenericMapResponse(Map genericMapResponse) { + ApiResponses apiResponses = new ApiResponses(); + genericMapResponse.forEach(apiResponses::addApiResponse); + this.genericMapResponse = genericMapResponse; + return apiResponses; + } + + /** + * Gets generic map response. + * + * @return the generic map response + */ + public Map getGenericMapResponse() { + return genericMapResponse; + } + + /** + * Gets locale. + * + * @return the locale + */ + public Locale getLocale() { + return locale; + } + + /** + * Is use return type schema boolean. + * + * @return the boolean + */ + public boolean isUseReturnTypeSchema() { + return useReturnTypeSchema; + } + + /** + * Sets use return type schema. + * + * @param useReturnTypeSchema the use return type schema + */ + public void setUseReturnTypeSchema(boolean useReturnTypeSchema) { + this.useReturnTypeSchema = useReturnTypeSchema; + } + + public void calculateConsumesProduces(Method method) { + fillMethods(methodProduces, methodConsumes, null); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIGenerator.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIGenerator.java new file mode 100644 index 00000000000..694146d1391 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIGenerator.java @@ -0,0 +1,397 @@ +/* + * 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 org.apache.dubbo.metadata.swagger; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.metadata.swagger.model.Components; +import org.apache.dubbo.metadata.swagger.model.OpenAPI; +import org.apache.dubbo.metadata.swagger.model.Operation; +import org.apache.dubbo.metadata.swagger.model.PathItem; +import org.apache.dubbo.metadata.swagger.model.PathItem.HttpMethod; +import org.apache.dubbo.metadata.swagger.model.Paths; +import org.apache.dubbo.metadata.swagger.model.media.StringSchema; +import org.apache.dubbo.metadata.swagger.model.parameters.Parameter; +import org.apache.dubbo.metadata.swagger.model.responses.ApiResponses; +import org.apache.dubbo.metadata.swagger.utils.PathUtils; +import org.apache.dubbo.remoting.http12.HttpMethods; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.DefaultRequestMappingRegistry; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.RequestMapping; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.condition.PathExpression; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.HandlerMeta; + +import java.lang.reflect.Method; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.DEFAULT_CONSUMES_MEDIA_TYPE; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.DEFAULT_PRODUCES_MEDIA_TYPE; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.PATH; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.QUERY; +import static org.apache.dubbo.metadata.swagger.model.PathItem.HttpMethod.DELETE; +import static org.apache.dubbo.metadata.swagger.model.PathItem.HttpMethod.GET; +import static org.apache.dubbo.metadata.swagger.model.PathItem.HttpMethod.PATCH; +import static org.apache.dubbo.metadata.swagger.model.PathItem.HttpMethod.POST; +import static org.apache.dubbo.metadata.swagger.model.PathItem.HttpMethod.PUT; + +public class OpenAPIGenerator { + private final Logger LOGGER = LoggerFactory.getLogger(OpenAPIGenerator.class); + private final Lock reentrantLock = new ReentrantLock(); + private final DefaultRequestMappingRegistry defaultRequestMappingRegistry; + private final OpenAPIService openAPIService; + private final ResponseService responseBuilder; + private final RequestService requestBuilder; + + private final Pattern pathPattern = Pattern.compile("\\{(.*?)}"); + + public OpenAPIGenerator( + DefaultRequestMappingRegistry defaultRequestMappingRegistry, + RequestService requestService, + OpenAPIService openAPIService, + ResponseService responseBuilder) { + super(); + this.openAPIService = openAPIService; + this.responseBuilder = responseBuilder; + this.requestBuilder = requestService; + this.defaultRequestMappingRegistry = defaultRequestMappingRegistry; + } + + public OpenAPI getOpenApi(Locale locale) { + this.reentrantLock.lock(); + try { + final OpenAPI openAPI; + final Locale finalLocale = locale == null ? Locale.getDefault() : locale; + if (openAPIService.getCachedOpenAPI(finalLocale) == null) { + Instant start = Instant.now(); + + openAPI = openAPIService.build(); + + this.getPaths(finalLocale, openAPI); + + openAPIService.setServersPresent(!CollectionUtils.isEmpty(openAPI.getServers())); + + openAPIService.updateServers(openAPI); + + openAPIService.setCachedOpenAPI(openAPI, finalLocale); + + LOGGER.info( + "Init duration for springdoc-openapi is: {} ms", + Duration.between(start, Instant.now()).toMillis()); + } else { + LOGGER.debug("Fetching openApi document from cache"); + openAPI = openAPIService.getCachedOpenAPI(finalLocale); + openAPIService.updateServers(openAPI); + } + openAPIService.updateServers(openAPI); + return openAPI; + } finally { + this.reentrantLock.unlock(); + } + } + + protected void getPaths(Locale locale, OpenAPI openAPI) { + Map map = defaultRequestMappingRegistry.getRegistrations(); + this.calculatePath(map, locale, openAPI); + } + + private void calculatePath(Map map, Locale locale, OpenAPI openAPI) { + for (Entry entry : map.entrySet()) { + RequestMapping requestMappingInfo = entry.getKey(); + HandlerMeta handlerMeta = entry.getValue(); + List patterns = + requestMappingInfo.getPathCondition().getExpressions(); + if (!CollectionUtils.isEmpty(patterns)) { + Map regexMap = new LinkedHashMap<>(); + + for (PathExpression pattern : patterns) { + String operationPath = PathUtils.parsePath(pattern.toString(), regexMap); + String[] produces = requestMappingInfo.getProducesCondition().getMediaTypes().stream() + .map(mediaType -> mediaType.getType() + "/" + mediaType.getSubType()) + .toArray(String[]::new); + + String[] consumes = requestMappingInfo.getConsumesCondition().getMediaTypes().stream() + .map(mediaType -> mediaType.getType() + "/" + mediaType.getSubType()) + .toArray(String[]::new); + + String[] headers = requestMappingInfo.getHeadersCondition().getExpressions().stream() + .map(Object::toString) + .toArray(String[]::new); + String[] params = requestMappingInfo.getParamsCondition().getExpressions().stream() + .map(Object::toString) + .toArray(String[]::new); + + Set requestMethods = + entry.getKey().getMethodsCondition().getMethods(); + if (requestMethods.isEmpty()) { + requestMethods = this.getDefaultAllowedHttpMethods(); + } + + calculatePath( + handlerMeta, + operationPath, + requestMethods, + consumes, + produces, + headers, + params, + locale, + openAPI); + } + } + } + } + + private void calculatePath( + HandlerMeta handlerMeta, + String operationPath, + Set requestMethods, + String[] consumes, + String[] produces, + String[] headers, + String[] params, + Locale locale, + OpenAPI openAPI) { + this.calculatePath( + handlerMeta, + new RouterOperation( + operationPath, + requestMethods.toArray(new HttpMethod[requestMethods.size()]), + consumes, + produces, + headers, + params), + locale, + openAPI); + } + + private void calculatePath( + HandlerMeta handlerMeta, RouterOperation routerOperation, Locale locale, OpenAPI openAPI) { + String operationPath = routerOperation.getPath(); + Set httpMethods = new TreeSet<>(Arrays.asList(routerOperation.getMethods())); + String[] methodConsumes = routerOperation.getConsumes(); + String[] methodProduces = routerOperation.getProduces(); + String[] headers = routerOperation.getHeaders(); + Map queryParams = routerOperation.getQueryParams(); + + Components components = openAPI.getComponents(); + Paths paths = openAPI.getPaths(); + + Map operationMap = null; + if (paths.containsKey(operationPath)) { + PathItem pathItem = paths.get(operationPath); + operationMap = pathItem.readOperationsMap(); + } + + for (HttpMethod httpMethod : httpMethods) { + Operation existingOperation = this.getExistingOperation(operationMap, httpMethod); + Method method = handlerMeta.getMethod().getMethod(); + MethodAttributes methodAttributes = new MethodAttributes( + DEFAULT_CONSUMES_MEDIA_TYPE, + DEFAULT_PRODUCES_MEDIA_TYPE, + methodConsumes, + methodProduces, + headers, + locale); + methodAttributes.setMethodOverloaded(existingOperation != null); + + methodAttributes.calculateConsumesProduces(method); + + Operation operation = (existingOperation != null) ? existingOperation : new Operation(); + + this.fillParametersList(operation, queryParams, methodAttributes); + + // RequestBody in Operation + requestBuilder + .getRequestBodyBuilder() + .buildRequestBodyFromDoc(methodAttributes, components, locale) + .ifPresent(operation::setRequestBody); + + // request + operation = requestBuilder.build(handlerMeta, httpMethod, operation, methodAttributes, openAPI); + + // response + ApiResponses apiResponses = responseBuilder.build(components, handlerMeta, operation, methodAttributes); + operation.setResponses(apiResponses); + + PathItem pathItemObject = this.buildPathItem(httpMethod, operation, operationPath, paths); + + if (!StringUtils.contains(operationPath, "**")) { + if (StringUtils.contains(operationPath, "*")) { + Matcher matcher = pathPattern.matcher(operationPath); + while (matcher.find()) { + String pathParam = matcher.group(1); + String newPathParam = pathParam.replace("*", ""); + operationPath = operationPath.replace("{" + pathParam + "}", "{" + newPathParam + "}"); + } + } + paths.addPathItem(operationPath, pathItemObject); + } + } + } + + private void fillParametersList( + Operation operation, Map queryParams, MethodAttributes methodAttributes) { + List parametersList = operation.getParameters(); + if (parametersList == null) { + parametersList = new ArrayList<>(); + } + Collection headersMap = RequestService.getHeaders(methodAttributes, new LinkedHashMap<>()); + headersMap.forEach(parameter -> { + boolean exists = false; + if (!CollectionUtils.isEmpty(operation.getParameters())) { + for (Parameter p : operation.getParameters()) { + if (parameter.getName().equals(p.getName())) { + exists = true; + break; + } + } + } + if (!exists) { + operation.addParametersItem(parameter); + } + }); + if (!CollectionUtils.isEmptyMap(queryParams)) { + for (Map.Entry entry : queryParams.entrySet()) { + Parameter parameter = new Parameter(); + parameter.setName(entry.getKey()); + parameter.setSchema(new StringSchema()._default(entry.getValue())); + parameter.setRequired(true); + parameter.setIn(QUERY); + ParameterService.mergeParameter(parametersList, parameter); + } + operation.setParameters(parametersList); + } + } + + private PathItem buildPathItem(HttpMethod httpMethod, Operation operation, String operationPath, Paths paths) { + PathItem pathItemObject = null; + if (operation != null && !CollectionUtils.isEmpty(operation.getParameters())) { + Iterator paramIt = operation.getParameters().iterator(); + while (paramIt.hasNext()) { + Parameter parameter = paramIt.next(); + if (PATH.equals(parameter.getIn())) { + // check it's present in the path + String name = parameter.getName(); + if (!StringUtils.containsAny(operationPath, "{" + name + "}", "{*" + name + "}")) { + paramIt.remove(); + } + } + } + } + if (paths.containsKey(operationPath)) { + pathItemObject = paths.get(operationPath); + } else { + pathItemObject = new PathItem(); + } + + switch (httpMethod) { + case POST: + pathItemObject.post(operation); + break; + case GET: + pathItemObject.get(operation); + break; + case DELETE: + pathItemObject.delete(operation); + break; + case PUT: + pathItemObject.put(operation); + break; + case PATCH: + pathItemObject.patch(operation); + break; + case TRACE: + pathItemObject.trace(operation); + break; + case HEAD: + pathItemObject.head(operation); + break; + case OPTIONS: + pathItemObject.options(operation); + break; + default: + // Do nothing here + break; + } + return pathItemObject; + } + + private Operation getExistingOperation(Map operationMap, HttpMethod httpMethod) { + Operation existingOperation = null; + if (!CollectionUtils.isEmptyMap(operationMap)) { + // Get existing operation definition + switch (httpMethod) { + case GET: + existingOperation = operationMap.get(HttpMethod.GET); + break; + case POST: + existingOperation = operationMap.get(HttpMethod.POST); + break; + case PUT: + existingOperation = operationMap.get(HttpMethod.PUT); + break; + case DELETE: + existingOperation = operationMap.get(HttpMethod.DELETE); + break; + case PATCH: + existingOperation = operationMap.get(HttpMethod.PATCH); + break; + case HEAD: + existingOperation = operationMap.get(HttpMethod.HEAD); + break; + case OPTIONS: + existingOperation = operationMap.get(HttpMethod.OPTIONS); + break; + default: + // Do nothing here + break; + } + } + return existingOperation; + } + + protected Set getDefaultAllowedHttpMethods() { + String[] allowedRequestMethods = { + GET.toString(), + POST.toString(), + PUT.toString(), + PATCH.toString(), + DELETE.toString(), + HttpMethods.OPTIONS.toString(), + HttpMethods.HEAD.toString() + }; + return new HashSet<>(Arrays.asList(allowedRequestMethods)); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIService.java new file mode 100644 index 00000000000..88ec41ca5e9 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIService.java @@ -0,0 +1,116 @@ +/* + * 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 org.apache.dubbo.metadata.swagger; + +import org.apache.dubbo.common.json.impl.JacksonImpl; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.metadata.swagger.model.Components; +import org.apache.dubbo.metadata.swagger.model.OpenAPI; +import org.apache.dubbo.metadata.swagger.model.Paths; +import org.apache.dubbo.metadata.swagger.model.info.Info; +import org.apache.dubbo.metadata.swagger.model.servers.Server; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import com.google.gson.JsonParseException; + +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.DEFAULT_SERVER_DESCRIPTION; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.DEFAULT_TITLE; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.DEFAULT_VERSION; + +public class OpenAPIService { + + Logger LOGGER = LoggerFactory.getLogger(OpenAPI.class); + /** + * The Cached open api map. + */ + private final Map cachedOpenAPI = new HashMap<>(); + + /** + * The Server base url. + */ + private String serverBaseUrl; + + private OpenAPI openAPI; + + public OpenAPI getCachedOpenAPI(Locale locale) { + return cachedOpenAPI.get(locale.toLanguageTag()); + } + + public void setCachedOpenAPI(OpenAPI cachedOpenAPI, Locale locale) { + this.cachedOpenAPI.put(locale.toLanguageTag(), cachedOpenAPI); + } + + public void setServerBaseUrl(String serverBaseUrl) { + this.serverBaseUrl = serverBaseUrl; + } + + public void setServersPresent(boolean serversPresent) { + isServersPresent = serversPresent; + } + + private boolean isServersPresent; + + public OpenAPIService(OpenAPI openAPI) { + if (openAPI != null) { + this.openAPI = openAPI; + if (this.openAPI.getComponents() == null) this.openAPI.setComponents(new Components()); + if (this.openAPI.getPaths() == null) this.openAPI.setPaths(new Paths()); + if (!CollectionUtils.isEmpty(this.openAPI.getServers())) this.isServersPresent = true; + } + } + + public OpenAPI build() { + OpenAPI calculatedOpenAPI = null; + if (openAPI == null) { + calculatedOpenAPI = new OpenAPI(); + calculatedOpenAPI.setComponents(new Components()); + calculatedOpenAPI.setPaths(new Paths()); + } else { + try { + JacksonImpl jackson = new JacksonImpl(); + String jsonString = jackson.toJson(openAPI); + calculatedOpenAPI = jackson.toJavaObject(jsonString, OpenAPI.class); + } catch (JsonParseException e) { + LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage()); + calculatedOpenAPI = openAPI; + } + } + + if (calculatedOpenAPI != null && calculatedOpenAPI.getInfo() == null) { + Info infos = new Info().title(DEFAULT_TITLE).version(DEFAULT_VERSION); + calculatedOpenAPI.setInfo(infos); + } + + return calculatedOpenAPI; + } + + public void updateServers(OpenAPI openAPI) { + if (serverBaseUrl != null) { + Server server = new Server().url(serverBaseUrl).description(DEFAULT_SERVER_DESCRIPTION); + List servers = new ArrayList<>(); + servers.add(server); + openAPI.setServers(servers); + } + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/ParameterService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/ParameterService.java new file mode 100644 index 00000000000..547fb9c3d65 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/ParameterService.java @@ -0,0 +1,332 @@ +/* + * 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 org.apache.dubbo.metadata.swagger; + +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.metadata.swagger.model.Components; +import org.apache.dubbo.metadata.swagger.model.media.ArraySchema; +import org.apache.dubbo.metadata.swagger.model.media.FileSchema; +import org.apache.dubbo.metadata.swagger.model.media.ObjectSchema; +import org.apache.dubbo.metadata.swagger.model.media.Schema; +import org.apache.dubbo.metadata.swagger.model.parameters.Parameter; +import org.apache.dubbo.metadata.swagger.model.parameters.ParameterInfo; +import org.apache.dubbo.metadata.swagger.model.parameters.RequestBodyInfo; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ParameterMeta; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.COMPONENTS_REF; + +public class ParameterService { + + public static Parameter mergeParameter(List operationParameters, Parameter parameter) { + Parameter result = parameter; + if (parameter != null && parameter.getName() != null) { + final String name = parameter.getName(); + final String in = parameter.getIn(); + + Parameter paramDoc = operationParameters.stream() + .filter(p -> name.equals(p.getName()) + && (StringUtils.isEmpty(in) || StringUtils.isEmpty(p.getIn()) || in.equals(p.getIn()))) + .findAny() + .orElse(null); + if (paramDoc != null) { + mergeParameter(parameter, paramDoc); + result = paramDoc; + } else { + operationParameters.add(result); + } + } + return result; + } + + public static void mergeParameter(Parameter parameter, Parameter paramDoc) { + if (StringUtils.isBlank(paramDoc.getDescription())) { + paramDoc.setDescription(parameter.getDescription()); + } + + if (StringUtils.isBlank(paramDoc.getIn())) { + paramDoc.setIn(parameter.getIn()); + } + + if (paramDoc.getExample() == null) { + paramDoc.setExample(parameter.getExample()); + } + + if (paramDoc.getDeprecated() == null) { + paramDoc.setDeprecated(parameter.getDeprecated()); + } + + if (paramDoc.getRequired() == null) { + paramDoc.setRequired(parameter.getRequired()); + } + + if (paramDoc.getAllowEmptyValue() == null) { + paramDoc.setAllowEmptyValue(parameter.getAllowEmptyValue()); + } + + if (paramDoc.getAllowReserved() == null) { + paramDoc.setAllowReserved(parameter.getAllowReserved()); + } + + if (StringUtils.isBlank(paramDoc.get$ref())) { + paramDoc.set$ref(paramDoc.get$ref()); + } + + if (paramDoc.getSchema() == null && paramDoc.getContent() == null) { + paramDoc.setSchema(parameter.getSchema()); + } + + if (paramDoc.getExtensions() == null) { + paramDoc.setExtensions(parameter.getExtensions()); + } + + if (paramDoc.getStyle() == null) { + paramDoc.setStyle(parameter.getStyle()); + } + + if (paramDoc.getExplode() == null) { + paramDoc.setExplode(parameter.getExplode()); + } + } + + public Schema calculateSchema( + Components components, ParameterInfo parameterInfo, RequestBodyInfo requestBodyInfo) { + Schema schemaN; + String paramName = parameterInfo.getpName(); + ParameterMeta parameter = parameterInfo.getMethodParameter(); + + if (parameterInfo.getParameterModel() == null + || parameterInfo.getParameterModel().getSchema() == null) { + Type type = parameter.getGenericType(); + schemaN = this.extractSchema(components, type); + } else { + schemaN = parameterInfo.getParameterModel().getSchema(); + } + + if (requestBodyInfo != null) { + schemaN = this.calculateRequestBodySchema(components, parameterInfo, requestBodyInfo, schemaN, paramName); + } + + return schemaN; + } + + private Schema calculateRequestBodySchema( + Components components, + ParameterInfo parameterInfo, + RequestBodyInfo requestBodyInfo, + Schema schemaN, + String paramName) { + if (schemaN != null + && org.apache.commons.lang3.StringUtils.isEmpty(schemaN.getDescription()) + && parameterInfo.getParameterModel() != null) { + String description = parameterInfo.getParameterModel().getDescription(); + if (schemaN.get$ref() != null && schemaN.get$ref().contains(COMPONENTS_REF)) { + String key = schemaN.get$ref().substring(21); + Schema existingSchema = components.getSchemas().get(key); + if (!org.apache.commons.lang3.StringUtils.isEmpty(description)) + existingSchema.setDescription(description); + } else schemaN.setDescription(description); + } + + if (requestBodyInfo.getMergedSchema() != null) { + requestBodyInfo.getMergedSchema().addProperty(paramName, schemaN); + schemaN = requestBodyInfo.getMergedSchema(); + } else if (schemaN instanceof FileSchema + || schemaN instanceof ArraySchema && ((ArraySchema) schemaN).getItems() instanceof FileSchema) { + schemaN = new ObjectSchema().addProperty(paramName, schemaN); + requestBodyInfo.setMergedSchema(schemaN); + } else requestBodyInfo.addProperties(paramName, schemaN); + + if (requestBodyInfo.getMergedSchema() != null && parameterInfo.isRequired()) + requestBodyInfo.getMergedSchema().addRequiredItem(parameterInfo.getpName()); + + return schemaN; + } + + private Schema extractSchema(Components components, Type type) { + if (type == null) { + return null; + } + + if (type == String.class) { + Schema schema = new Schema<>(); + schema.setType("string"); + return schema; + } else if (type == Integer.class || type == int.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int32"); + return schema; + } else if (type == Long.class || type == long.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int64"); + return schema; + } else if (type == Short.class || type == short.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int32"); + return schema; + } else if (type == Byte.class || type == byte.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int32"); + return schema; + } else if (type == Boolean.class || type == boolean.class) { + Schema schema = new Schema<>(); + schema.setType("boolean"); + return schema; + } else if (type == Double.class || type == double.class) { + Schema schema = new Schema<>(); + schema.setType("number"); + schema.setFormat("double"); + return schema; + } else if (type == Float.class || type == float.class) { + Schema schema = new Schema<>(); + schema.setType("number"); + schema.setFormat("float"); + return schema; + } else if (type == BigDecimal.class) { + Schema schema = new Schema<>(); + schema.setType("number"); + schema.setFormat("double"); + return schema; + } else if (type == BigInteger.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int64"); + return schema; + } else if (type == Date.class) { + Schema schema = new Schema<>(); + schema.setType("string"); + schema.setFormat("date-time"); + return schema; + } else if (type == LocalDate.class) { + Schema schema = new Schema<>(); + schema.setType("string"); + schema.setFormat("date"); + return schema; + } else if (type == LocalDateTime.class) { + Schema schema = new Schema<>(); + schema.setType("string"); + schema.setFormat("date-time"); + return schema; + } else if (type instanceof Class) { + Class clazz = (Class) type; + String schemaName = clazz.getSimpleName(); + + if (components.getSchemas() != null && components.getSchemas().containsKey(schemaName)) { + Schema refSchema = new Schema<>(); + refSchema.$ref(COMPONENTS_REF + schemaName); + return refSchema; + } + + if (clazz.isEnum()) { + Schema schema = new Schema<>(); + schema.setType("string"); + List enumValues = Arrays.stream(clazz.getEnumConstants()) + .map(Object::toString) + .collect(Collectors.toList()); + schema.setEnum(enumValues); + + components.addSchemas(schemaName, schema); + + Schema refSchema = new Schema<>(); + refSchema.$ref(COMPONENTS_REF + schemaName); + return refSchema; + } else { + Schema schema = new Schema<>(); + schema.setType("object"); + Map properties = extractPropertiesSchema(components, clazz); + schema.setProperties(properties); + + components.addSchemas(schemaName, schema); + + Schema refSchema = new Schema<>(); + refSchema.$ref(COMPONENTS_REF + schemaName); + return refSchema; + } + } else if (type instanceof ParameterizedType) { + return calculateSchemaFromParameterizedType(components, (ParameterizedType) type); + } else { + Schema schema = new Schema<>(); + schema.setType("string"); + return schema; + } + } + + private Schema calculateSchemaFromParameterizedType(Components components, ParameterizedType parameterizedType) { + Type rawType = parameterizedType.getRawType(); + Type[] typeArguments = parameterizedType.getActualTypeArguments(); + + if (rawType == List.class || rawType == Collection.class) { + // 处理列表类型 + Schema schema = new Schema<>(); + schema.setType("array"); + Schema itemsSchema = extractSchema(components, typeArguments[0]); + schema.setItems(itemsSchema); + return schema; + } else if (rawType == Map.class) { + // 处理映射类型 + Schema schema = new Schema<>(); + schema.setType("object"); + // 对于 Map 类型,我们可以设置 additionalProperties + Schema valueSchema = extractSchema(components, typeArguments[1]); + schema.setAdditionalProperties(valueSchema); + return schema; + } else { + // 其他参数化类型,按对象处理 + Schema schema = new Schema<>(); + schema.setType("object"); + // 如果需要,可以进一步处理泛型类型 + return schema; + } + } + + private Map extractPropertiesSchema(Components components, Class clazz) { + Map properties = new LinkedHashMap<>(); + + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())) { + continue; + } + + String fieldName = field.getName(); + Type fieldType = field.getGenericType(); + Schema fieldSchema = extractSchema(components, fieldType); + properties.put(fieldName, fieldSchema); + } + + return properties; + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RequestBodyService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RequestBodyService.java new file mode 100644 index 00000000000..606dc432321 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RequestBodyService.java @@ -0,0 +1,104 @@ +/* + * 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 org.apache.dubbo.metadata.swagger; + +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.metadata.swagger.model.Components; +import org.apache.dubbo.metadata.swagger.model.media.Content; +import org.apache.dubbo.metadata.swagger.model.media.MediaType; +import org.apache.dubbo.metadata.swagger.model.media.Schema; +import org.apache.dubbo.metadata.swagger.model.parameters.ParameterInfo; +import org.apache.dubbo.metadata.swagger.model.parameters.RequestBody; +import org.apache.dubbo.metadata.swagger.model.parameters.RequestBodyInfo; + +import java.util.Locale; +import java.util.Optional; + +public class RequestBodyService { + + /** + * The Parameter builder. + */ + private final ParameterService parameterBuilder; + + public RequestBodyService(ParameterService parameterBuilder) { + super(); + this.parameterBuilder = parameterBuilder; + } + + public void calculateRequestBodyInfo( + Components components, + MethodAttributes methodAttributes, + ParameterInfo parameterInfo, + RequestBodyInfo requestBodyInfo) { + RequestBody requestBody = requestBodyInfo.getRequestBody(); + + String paramName = null; + paramName = StringUtils.defaultIfEmpty(paramName, parameterInfo.getpName()); + parameterInfo.setpName(paramName); + + requestBody = this.buildRequestBody(requestBody, components, methodAttributes, parameterInfo, requestBodyInfo); + requestBodyInfo.setRequestBody(requestBody); + } + + private RequestBody buildRequestBody( + RequestBody requestBody, + Components components, + MethodAttributes methodAttributes, + ParameterInfo parameterInfo, + RequestBodyInfo requestBodyInfo) { + if (requestBody == null) { + requestBody = new RequestBody(); + requestBodyInfo.setRequestBody(requestBody); + } + + if (requestBody.getContent() == null) { + Schema schema = parameterBuilder.calculateSchema(components, parameterInfo, requestBodyInfo); + this.buildContent(requestBody, methodAttributes, schema); + } else { + Schema schema = parameterBuilder.calculateSchema(components, parameterInfo, requestBodyInfo); + this.mergeContent(requestBody, methodAttributes, schema); + } + + return requestBody; + } + + private void mergeContent(RequestBody requestBody, MethodAttributes methodAttributes, Schema schema) { + Content content = requestBody.getContent(); + buildContent(requestBody, methodAttributes, schema, content); + } + + private void buildContent( + RequestBody requestBody, MethodAttributes methodAttributes, Schema schema, Content content) { + for (String value : methodAttributes.getMethodConsumes()) { + MediaType mediaTypeObject = new MediaType(); + mediaTypeObject.setSchema(schema); + content.addMediaType(value, mediaTypeObject); + } + requestBody.setContent(content); + } + + private void buildContent(RequestBody requestBody, MethodAttributes methodAttributes, Schema schema) { + Content content = new Content(); + buildContent(requestBody, methodAttributes, schema, content); + } + + public Optional buildRequestBodyFromDoc( + MethodAttributes methodAttributes, Components components, Locale locale) { + return Optional.empty(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RequestService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RequestService.java new file mode 100644 index 00000000000..09616b8d45c --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RequestService.java @@ -0,0 +1,229 @@ +/* + * 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 org.apache.dubbo.metadata.swagger; + +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.metadata.swagger.model.Components; +import org.apache.dubbo.metadata.swagger.model.OpenAPI; +import org.apache.dubbo.metadata.swagger.model.Operation; +import org.apache.dubbo.metadata.swagger.model.OperationService; +import org.apache.dubbo.metadata.swagger.model.PathItem.HttpMethod; +import org.apache.dubbo.metadata.swagger.model.media.Schema; +import org.apache.dubbo.metadata.swagger.model.media.StringSchema; +import org.apache.dubbo.metadata.swagger.model.parameters.Parameter; +import org.apache.dubbo.metadata.swagger.model.parameters.ParameterId; +import org.apache.dubbo.metadata.swagger.model.parameters.ParameterInfo; +import org.apache.dubbo.metadata.swagger.model.parameters.RequestBody; +import org.apache.dubbo.metadata.swagger.model.parameters.RequestBodyInfo; +import org.apache.dubbo.metadata.swagger.utils.PrimitiveType; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.HandlerMeta; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ParameterMeta; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; + +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.COOKIE; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.DEFAULT_NONE; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.HEADER; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.MULTIPART_FORM_DATA_VALUE; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.PATH; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.QUERY; + +public class RequestService { + + private final ParameterService parameterBuilder; + + private final RequestBodyService requestBodyService; + + private final OperationService operationService; + + public RequestService( + ParameterService parameterBuilder, + RequestBodyService requestBodyService, + OperationService operationService) { + super(); + this.parameterBuilder = parameterBuilder; + this.requestBodyService = requestBodyService; + this.operationService = operationService; + } + + public static Collection getHeaders( + MethodAttributes methodAttributes, LinkedHashMap map) { + for (Map.Entry entry : methodAttributes.getHeaders().entrySet()) { + StringSchema schema = new StringSchema(); + if (StringUtils.isNotEmpty(entry.getValue())) schema.addEnumItem(entry.getValue()); + Parameter parameter = + new Parameter().in(HEADER).name(entry.getKey()).schema(schema); + ParameterId parameterId = new ParameterId(parameter); + if (map.containsKey(parameterId)) { + parameter = map.get(parameterId); + List existingEnum = null; + if (parameter.getSchema() != null + && !CollectionUtils.isEmpty(parameter.getSchema().getEnum())) + existingEnum = parameter.getSchema().getEnum(); + if (StringUtils.isNotEmpty(entry.getValue()) + && (existingEnum == null || !existingEnum.contains(entry.getValue()))) + parameter.getSchema().addEnumItemObject(entry.getValue()); + parameter.setSchema(parameter.getSchema()); + } + map.put(parameterId, parameter); + } + return map.values(); + } + + public Operation build( + HandlerMeta handlerMeta, + HttpMethod httpMethod, + Operation operation, + MethodAttributes methodAttributes, + OpenAPI openAPI) { + String operationId = operationService.getOperationId( + handlerMeta.getMethod().getMethod().getName(), operation.getOperationId(), openAPI); + operation.setOperationId(operationId); + + ParameterMeta[] parameters = handlerMeta.getParameters(); + + RequestBodyInfo requestBodyInfo = new RequestBodyInfo(); + List operationParameters = + (operation.getParameters() != null) ? operation.getParameters() : new ArrayList<>(); + Components components = openAPI.getComponents(); + + for (ParameterMeta parameterMeta : parameters) { + Parameter parameter; + final String pName = parameterMeta.getName(); + ParameterInfo parameterInfo = new ParameterInfo(pName, parameterMeta, parameterBuilder); + + parameter = this.buildParams(parameterInfo, components, httpMethod, methodAttributes, openAPI.getOpenapi()); + // Merge with the operation parameters + ParameterService.mergeParameter(operationParameters, parameter); + + if (!HttpMethod.GET.equals(httpMethod)) { + if (operation.getRequestBody() != null) requestBodyInfo.setRequestBody(operation.getRequestBody()); + requestBodyService.calculateRequestBodyInfo( + components, methodAttributes, parameterInfo, requestBodyInfo); + } + } + + LinkedHashMap map = this.getParameterLinkedHashMap(operationParameters); + RequestBody requestBody = requestBodyInfo.getRequestBody(); + + // support form-data + if (requestBody != null + && requestBody.getContent() != null + && requestBody.getContent().containsKey(MULTIPART_FORM_DATA_VALUE)) { + Iterator> it = map.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + Parameter parameter = entry.getValue(); + if (!PATH.equals(parameter.getIn()) + && !HEADER.equals(parameter.getIn()) + && !COOKIE.equals(parameter.getIn())) { + Schema itemSchema = new Schema<>(); + itemSchema.setName(entry.getKey().getpName()); + requestBodyInfo.addProperties(entry.getKey().getpName(), itemSchema); + it.remove(); + } + } + } + return operation; + } + + private LinkedHashMap getParameterLinkedHashMap(List operationParameters) { + LinkedHashMap map = operationParameters.stream() + .collect(Collectors.toMap( + ParameterId::new, + parameter -> parameter, + (u, v) -> { + throw new IllegalStateException(String.format("Duplicate key %s", u)); + }, + LinkedHashMap::new)); + + map.forEach((parameterId, parameter) -> { + if (StringUtils.isBlank(parameter.getIn()) && StringUtils.isBlank(parameter.get$ref())) + parameter.setIn(QUERY); + }); + return map; + } + + private Parameter buildParams( + ParameterInfo parameterInfo, + Components components, + HttpMethod httpMethod, + MethodAttributes methodAttributes, + String openapi) { + if (parameterInfo.getParamType() != null) { + if (!DEFAULT_NONE.equals(parameterInfo.getDefaultValue())) { + parameterInfo.setRequired(false); + } else { + parameterInfo.setDefaultValue(null); + } + return this.buildParam(parameterInfo, components); + } + return null; + } + + private Parameter buildParam(ParameterInfo parameterInfo, Components components) { + Parameter parameter = parameterInfo.getParameterModel(); + String name = parameterInfo.getpName(); + + if (parameter == null) { + parameter = new Parameter(); + parameterInfo.setParameterModel(parameter); + } + + if (StringUtils.isBlank(parameter.getName())) { + parameter.setName(name); + } + + if (StringUtils.isBlank(parameter.getIn())) { + parameter.setIn(parameterInfo.getParamType()); + } + + if (parameter.getRequired() == null) { + parameter.setRequired(parameterInfo.isRequired()); + } + + if (parameter.getSchema() == null && parameter.getContent() == null) { + Schema schema = parameterBuilder.calculateSchema(components, parameterInfo, null); + if (parameterInfo.getDefaultValue() != null && schema != null) { + Object defaultValue = parameterInfo.getDefaultValue(); + // Cast default value + PrimitiveType primitiveType = PrimitiveType.fromTypeAndFormat(schema.getType(), schema.getFormat()); + if (primitiveType != null) { + Schema primitiveSchema = primitiveType.createProperty(); + primitiveSchema.setDefault(parameterInfo.getDefaultValue()); + defaultValue = primitiveSchema.getDefault(); + } + schema.setDefault(defaultValue); + } + parameter.setSchema(schema); + } + return parameter; + } + + public RequestBodyService getRequestBodyBuilder() { + return requestBodyService; + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/ResponseService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/ResponseService.java new file mode 100644 index 00000000000..7927b0d1c9f --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/ResponseService.java @@ -0,0 +1,367 @@ +/* + * 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 org.apache.dubbo.metadata.swagger; + +import org.apache.dubbo.common.utils.ArrayUtils; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.metadata.swagger.model.Components; +import org.apache.dubbo.metadata.swagger.model.Operation; +import org.apache.dubbo.metadata.swagger.model.media.ComposedSchema; +import org.apache.dubbo.metadata.swagger.model.media.Content; +import org.apache.dubbo.metadata.swagger.model.media.MediaType; +import org.apache.dubbo.metadata.swagger.model.media.Schema; +import org.apache.dubbo.metadata.swagger.model.responses.ApiResponse; +import org.apache.dubbo.metadata.swagger.model.responses.ApiResponses; +import org.apache.dubbo.remoting.http12.HttpStatus; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.HandlerMeta; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.MethodMeta; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.COMPONENTS_REF; +import static org.apache.dubbo.metadata.swagger.SwaggerConstants.DEFAULT_DESCRIPTION; + +public class ResponseService { + + private Map genericMapResponse = new LinkedHashMap<>(); + + public ApiResponses build( + Components components, HandlerMeta handlerMeta, Operation operation, MethodAttributes methodAttributes) { + final ApiResponses apiResponses = this.getApiResponses(operation); + // for each one build ApiResponse and add it to existing responses + for (Entry entry : genericMapResponse.entrySet()) { + apiResponses.addApiResponse(entry.getKey(), entry.getValue()); + } + + // Fill api Responses + this.computeResponse(components, handlerMeta.getMethod(), apiResponses, methodAttributes, false); + return apiResponses; + } + + private ApiResponses computeResponse( + Components components, + MethodMeta method, + ApiResponses apiResponses, + MethodAttributes methodAttributes, + boolean isGeneric) { + // Parsing documentation, if present + + if (!CollectionUtils.isEmptyMap(apiResponses) && (apiResponses.size() != genericMapResponse.size())) { + // API Responses at operation and @ApiResponse annotation + for (Map.Entry entry : apiResponses.entrySet()) { + String httpCode = entry.getKey(); + ApiResponse apiResponse = entry.getValue(); + buildApiResponses(components, method, apiResponses, methodAttributes, httpCode, apiResponse, isGeneric); + } + } else { + // Use response parameters with no description filled - No documentation + // available + String httpCode = HttpStatus.OK.toString(); + ApiResponse apiResponse = + genericMapResponse.containsKey(httpCode) ? genericMapResponse.get(httpCode) : new ApiResponse(); + if (httpCode != null) + buildApiResponses(components, method, apiResponses, methodAttributes, httpCode, apiResponse, isGeneric); + } + return apiResponses; + } + + private void buildApiResponses( + Components components, + MethodMeta method, + ApiResponses apiResponsesOp, + MethodAttributes methodAttributes, + String httpCode, + ApiResponse apiResponse, + boolean isGeneric) { + // No documentation + if (StringUtils.isBlank(apiResponse.get$ref())) { + if (apiResponse.getContent() == null) { + Content content = this.buildContent(components, method, methodAttributes.getMethodProduces()); + apiResponse.setContent(content); + } else if (CollectionUtils.isEmptyMap(apiResponse.getContent())) { + apiResponse.setContent(null); + } + if (StringUtils.isBlank(apiResponse.getDescription())) { + apiResponse.setDescription(DEFAULT_DESCRIPTION); + } + } + if (apiResponse.getContent() != null && ((isGeneric || methodAttributes.isMethodOverloaded()))) { + // Merge with existing schema + Content existingContent = apiResponse.getContent(); + Schema schemaN = this.calculateSchema(components, method.getGenericReturnType()); + if (schemaN != null && ArrayUtils.isNotEmpty(methodAttributes.getMethodProduces())) { + Arrays.stream(methodAttributes.getMethodProduces()) + .forEach(mediaTypeStr -> this.mergeSchema(existingContent, schemaN, mediaTypeStr)); + } + } + apiResponsesOp.addApiResponse(httpCode, apiResponse); + } + + private void mergeSchema(Content existingContent, Schema schemaN, String mediaTypeStr) { + if (existingContent.containsKey(mediaTypeStr)) { + MediaType mediaType = existingContent.get(mediaTypeStr); + if (!schemaN.equals(mediaType.getSchema())) { + // Merge the two schemas for the same mediaType + Schema firstSchema = mediaType.getSchema(); + ComposedSchema schemaObject; + if (firstSchema instanceof ComposedSchema) { + schemaObject = (ComposedSchema) firstSchema; + List listOneOf = schemaObject.getOneOf(); + if (!CollectionUtils.isEmpty(listOneOf) && !listOneOf.contains(schemaN)) + schemaObject.addOneOfItem(schemaN); + } else { + schemaObject = new ComposedSchema(); + schemaObject.addOneOfItem(schemaN); + schemaObject.addOneOfItem(firstSchema); + } + mediaType.setSchema(schemaObject); + existingContent.addMediaType(mediaTypeStr, mediaType); + } + } else { + // Add the new schema for a different mediaType + existingContent.addMediaType(mediaTypeStr, new MediaType().schema(schemaN)); + } + } + + public Schema calculateSchema(Components components, Type returnType) { + if (isVoid(returnType)) { + return null; + } + + Schema schemaN = null; + + if (returnType instanceof ParameterizedType) { + schemaN = calculateSchemaFromParameterizedType(components, (ParameterizedType) returnType); + } else { + schemaN = extractSchema(components, returnType); + } + + return schemaN; + } + + private Schema extractSchema(Components components, Type type) { + if (type == null) { + return null; + } + + if (type == String.class) { + Schema schema = new Schema<>(); + schema.setType("string"); + return schema; + } else if (type == Integer.class || type == int.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int32"); + return schema; + } else if (type == Long.class || type == long.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int64"); + return schema; + } else if (type == Short.class || type == short.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int32"); + return schema; + } else if (type == Byte.class || type == byte.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int32"); + return schema; + } else if (type == Boolean.class || type == boolean.class) { + Schema schema = new Schema<>(); + schema.setType("boolean"); + return schema; + } else if (type == Double.class || type == double.class) { + Schema schema = new Schema<>(); + schema.setType("number"); + schema.setFormat("double"); + return schema; + } else if (type == Float.class || type == float.class) { + Schema schema = new Schema<>(); + schema.setType("number"); + schema.setFormat("float"); + return schema; + } else if (type == BigDecimal.class) { + Schema schema = new Schema<>(); + schema.setType("number"); + schema.setFormat("double"); + return schema; + } else if (type == BigInteger.class) { + Schema schema = new Schema<>(); + schema.setType("integer"); + schema.setFormat("int64"); + return schema; + } else if (type == Date.class) { + Schema schema = new Schema<>(); + schema.setType("string"); + schema.setFormat("date-time"); + return schema; + } else if (type == LocalDate.class) { + Schema schema = new Schema<>(); + schema.setType("string"); + schema.setFormat("date"); + return schema; + } else if (type == LocalDateTime.class) { + Schema schema = new Schema<>(); + schema.setType("string"); + schema.setFormat("date-time"); + return schema; + } else if (type instanceof Class) { + Class clazz = (Class) type; + String schemaName = clazz.getSimpleName(); + + if (components.getSchemas() != null && components.getSchemas().containsKey(schemaName)) { + Schema refSchema = new Schema<>(); + refSchema.$ref(COMPONENTS_REF + schemaName); + return refSchema; + } + + if (clazz.isEnum()) { + Schema schema = new Schema<>(); + schema.setType("string"); + List enumValues = Arrays.stream(clazz.getEnumConstants()) + .map(Object::toString) + .collect(Collectors.toList()); + schema.setEnum(enumValues); + + components.addSchemas(schemaName, schema); + + Schema refSchema = new Schema<>(); + refSchema.$ref(COMPONENTS_REF + schemaName); + return refSchema; + } else { + Schema schema = new Schema<>(); + schema.setType("object"); + Map properties = extractPropertiesSchema(components, clazz); + schema.setProperties(properties); + + components.addSchemas(schemaName, schema); + + Schema refSchema = new Schema<>(); + refSchema.$ref(COMPONENTS_REF + schemaName); + return refSchema; + } + } else if (type instanceof ParameterizedType) { + return calculateSchemaFromParameterizedType(components, (ParameterizedType) type); + } else { + Schema schema = new Schema<>(); + schema.setType("string"); + return schema; + } + } + + private Schema calculateSchemaFromParameterizedType(Components components, ParameterizedType parameterizedType) { + Type rawType = parameterizedType.getRawType(); + Type[] typeArguments = parameterizedType.getActualTypeArguments(); + + if (rawType == List.class || rawType == Collection.class) { + // 处理列表类型 + Schema schema = new Schema<>(); + schema.setType("array"); + Schema itemsSchema = extractSchema(components, typeArguments[0]); + schema.setItems(itemsSchema); + return schema; + } else if (rawType == Map.class) { + // 处理映射类型 + Schema schema = new Schema<>(); + schema.setType("object"); + // 对于 Map 类型,我们可以设置 additionalProperties + Schema valueSchema = extractSchema(components, typeArguments[1]); + schema.setAdditionalProperties(valueSchema); + return schema; + } else { + // 其他参数化类型,按对象处理 + Schema schema = new Schema<>(); + schema.setType("object"); + // 如果需要,可以进一步处理泛型类型 + return schema; + } + } + + private Map extractPropertiesSchema(Components components, Class clazz) { + Map properties = new LinkedHashMap<>(); + + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())) { + continue; + } + + String fieldName = field.getName(); + Type fieldType = field.getGenericType(); + Schema fieldSchema = extractSchema(components, fieldType); + properties.put(fieldName, fieldSchema); + } + + return properties; + } + + private ApiResponses getApiResponses(Operation operation) { + ApiResponses apiResponses = operation.getResponses(); + if (apiResponses == null) apiResponses = new ApiResponses(); + return apiResponses; + } + + private boolean isVoid(Type returnType) { + if (returnType == Void.TYPE) { + return true; + } + if (returnType instanceof Class) { + return Void.class.equals(returnType); + } + return false; + } + + private Content buildContent(Components components, MethodMeta method, String[] methodProduces) { + Content content = new Content(); + Type returnType = method.getReturnType(); + if (isVoid(returnType)) { + // if void, no content + content = null; + } else if (ArrayUtils.isNotEmpty(methodProduces)) { + Schema schemaN = this.calculateSchema(components, returnType); + if (schemaN != null) { + MediaType mediaType = new MediaType(); + mediaType.setSchema(schemaN); + // Fill the content + setContent(methodProduces, content, mediaType); + } + } + return content; + } + + private void setContent(String[] methodProduces, Content content, MediaType mediaType) { + Arrays.stream(methodProduces).forEach(mediaTypeStr -> content.addMediaType(mediaTypeStr, mediaType)); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RouterOperation.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RouterOperation.java new file mode 100644 index 00000000000..b10510b19e7 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/RouterOperation.java @@ -0,0 +1,348 @@ +/* + * 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 org.apache.dubbo.metadata.swagger; + +import org.apache.dubbo.common.utils.ArrayUtils; +import org.apache.dubbo.metadata.swagger.model.Operation; +import org.apache.dubbo.metadata.swagger.model.PathItem.HttpMethod; + +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; + +/** + * The type Router operation. + * + * @author bnasslahsen + */ +public class RouterOperation implements Comparable { + + /** + * The Path. + */ + private String path; + + /** + * The Methods. + */ + private HttpMethod[] methods; + + /** + * The Consumes. + */ + private String[] consumes; + + /** + * The Produces. + */ + private String[] produces; + + /** + * The Headers. + */ + private String[] headers; + + /** + * The Params. + */ + private String[] params; + + /** + * The Bean class. + */ + private Class beanClass; + + /** + * The Bean method. + */ + private String beanMethod; + + /** + * The Parameter types. + */ + private Class[] parameterTypes; + + /** + * The Query params. + */ + private Map queryParams; + + /** + * The Operation model. + */ + private Operation operationModel; + + /** + * Instantiates a new Router operation. + */ + public RouterOperation() {} + + /** + * Instantiates a new Router operation. + * + * @param path the path + * @param methods the methods + * @param consumes the consumes + * @param produces the produces + * @param headers the headers + * @param params the params + */ + public RouterOperation( + String path, + HttpMethod[] methods, + String[] consumes, + String[] produces, + String[] headers, + String[] params) { + this.path = path; + this.methods = methods; + this.consumes = consumes; + this.produces = produces; + this.headers = headers; + this.params = params; + } + + /** + * Gets path. + * + * @return the path + */ + public String getPath() { + return path; + } + + /** + * Sets path. + * + * @param path the path + */ + public void setPath(String path) { + this.path = path; + } + + /** + * Get methods request method [ ]. + * + * @return the request method [ ] + */ + public HttpMethod[] getMethods() { + return methods; + } + + /** + * Sets methods. + * + * @param methods the methods + */ + public void setMethods(HttpMethod[] methods) { + this.methods = methods; + } + + /** + * Get consumes string [ ]. + * + * @return the string [ ] + */ + public String[] getConsumes() { + return consumes; + } + + /** + * Sets consumes. + * + * @param consumes the consumes + */ + public void setConsumes(String[] consumes) { + this.consumes = consumes; + } + + /** + * Get produces string [ ]. + * + * @return the string [ ] + */ + public String[] getProduces() { + return produces; + } + + /** + * Sets produces. + * + * @param produces the produces + */ + public void setProduces(String[] produces) { + this.produces = produces; + } + + /** + * Gets bean class. + * + * @return the bean class + */ + public Class getBeanClass() { + return beanClass; + } + + /** + * Sets bean class. + * + * @param beanClass the bean class + */ + public void setBeanClass(Class beanClass) { + this.beanClass = beanClass; + } + + /** + * Gets bean method. + * + * @return the bean method + */ + public String getBeanMethod() { + return beanMethod; + } + + /** + * Sets bean method. + * + * @param beanMethod the bean method + */ + public void setBeanMethod(String beanMethod) { + this.beanMethod = beanMethod; + } + + /** + * Get parameter types class [ ]. + * + * @return the class [ ] + */ + public Class[] getParameterTypes() { + return parameterTypes; + } + + /** + * Sets parameter types. + * + * @param parameterTypes the parameter types + */ + public void setParameterTypes(Class[] parameterTypes) { + this.parameterTypes = parameterTypes; + } + + /** + * Get headers string [ ]. + * + * @return the string [ ] + */ + public String[] getHeaders() { + return headers; + } + + /** + * Sets headers. + * + * @param headers the headers + */ + public void setHeaders(String[] headers) { + this.headers = headers; + } + + /** + * Gets query params. + * + * @return the query params + */ + public Map getQueryParams() { + return queryParams; + } + + /** + * Sets query params. + * + * @param queryParams the query params + */ + public void setQueryParams(Map queryParams) { + this.queryParams = queryParams; + } + + /** + * Gets params. + * + * @return the params + */ + public String[] getParams() { + return this.params; + } + + /** + * Sets params. + * + * @param params the params + */ + public void setParams(String[] params) { + this.params = params; + } + + @Override + public int compareTo(RouterOperation routerOperation) { + int result = path.compareTo(routerOperation.getPath()); + if (result == 0 && !ArrayUtils.isEmpty(methods)) + result = methods[0].compareTo(routerOperation.getMethods()[0]); + if (result == 0 && operationModel != null && routerOperation.getOperationModel() != null) + result = operationModel + .getOperationId() + .compareTo(routerOperation.getOperationModel().getOperationId()); + return result; + } + + private Operation getOperationModel() { + return operationModel; + } + + private void setOperationModel(Operation operation) { + this.operationModel = operation; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RouterOperation that = (RouterOperation) o; + return Objects.equals(path, that.path) + && Arrays.equals(methods, that.methods) + && Arrays.equals(consumes, that.consumes) + && Arrays.equals(produces, that.produces) + && Arrays.equals(headers, that.headers) + && Arrays.equals(params, that.params) + && Objects.equals(beanClass, that.beanClass) + && Objects.equals(beanMethod, that.beanMethod) + && Arrays.equals(parameterTypes, that.parameterTypes) + && Objects.equals(queryParams, that.queryParams) + && Objects.equals(operationModel, that.operationModel); + } + + @Override + public int hashCode() { + int result = Objects.hash(path, beanClass, beanMethod, queryParams, operationModel); + result = 31 * result + Arrays.hashCode(methods); + result = 31 * result + Arrays.hashCode(params); + result = 31 * result + Arrays.hashCode(consumes); + result = 31 * result + Arrays.hashCode(produces); + result = 31 * result + Arrays.hashCode(headers); + result = 31 * result + Arrays.hashCode(parameterTypes); + return result; + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/SwaggerConstants.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/SwaggerConstants.java new file mode 100644 index 00000000000..fb276631478 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/SwaggerConstants.java @@ -0,0 +1,51 @@ +/* + * 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 org.apache.dubbo.metadata.swagger; + +public class SwaggerConstants { + public static final String DEFAULT_CONSUMES_MEDIA_TYPE = "application/json"; + public static final String DEFAULT_PRODUCES_MEDIA_TYPE = "*/*"; + + public static final String DEFAULT = ""; + public static final String HEADER = "header"; + public static final String QUERY = "query"; + public static final String PATH = "path"; + public static final String COOKIE = "cookie"; + + /** + * The constant DEFAULT_TITLE. + */ + public static final String DEFAULT_TITLE = "OpenAPI definition"; + + /** + * The constant DEFAULT_VERSION. + */ + public static final String DEFAULT_VERSION = "v0"; + + /** + * The constant DEFAULT_SERVER_DESCRIPTION. + */ + public static final String DEFAULT_SERVER_DESCRIPTION = "Generated server url"; + + public static final String MULTIPART_FORM_DATA_VALUE = "multipart/form-data"; + + public static final String DEFAULT_NONE = "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n"; + + public static final String DEFAULT_DESCRIPTION = "default response"; + + public static final String COMPONENTS_REF = "#/components/schemas/"; +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Components.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Components.java new file mode 100644 index 00000000000..ec77457cac1 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Components.java @@ -0,0 +1,296 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; +import org.apache.dubbo.metadata.swagger.model.headers.Header; +import org.apache.dubbo.metadata.swagger.model.media.Schema; +import org.apache.dubbo.metadata.swagger.model.parameters.Parameter; +import org.apache.dubbo.metadata.swagger.model.parameters.RequestBody; +import org.apache.dubbo.metadata.swagger.model.responses.ApiResponse; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Components + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#componentsObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#componentsObject" + */ +public class Components { + + /** + * @since 2.1.6 + */ + public static final String COMPONENTS_SCHEMAS_REF = "#/components/schemas/"; + + private Map schemas = null; + private Map responses = null; + private Map parameters = null; + private Map requestBodies = null; + private Map headers = null; + private Map extensions = null; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Map pathItems; + + /** + * returns the schemas property from a Components instance. + * + * @return Map<String, Schema> schemas + **/ + public Map getSchemas() { + return schemas; + } + + public void setSchemas(Map schemas) { + this.schemas = schemas; + } + + public Components schemas(Map schemas) { + this.schemas = schemas; + return this; + } + + public Components addSchemas(String key, Schema schemasItem) { + if (this.schemas == null) { + this.schemas = new LinkedHashMap<>(); + } + this.schemas.put(key, schemasItem); + return this; + } + + /** + * returns the responses property from a Components instance. + * + * @return Map<String, ApiResponse> responses + **/ + public Map getResponses() { + return responses; + } + + public void setResponses(Map responses) { + this.responses = responses; + } + + public Components responses(Map responses) { + this.responses = responses; + return this; + } + + public Components addResponses(String key, ApiResponse responsesItem) { + if (this.responses == null) { + this.responses = new LinkedHashMap<>(); + } + this.responses.put(key, responsesItem); + return this; + } + + /** + * returns the parameters property from a Components instance. + * + * @return Map<String, Parameter> parameters + **/ + public Map getParameters() { + return parameters; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public Components parameters(Map parameters) { + this.parameters = parameters; + return this; + } + + public Components addParameters(String key, Parameter parametersItem) { + if (this.parameters == null) { + this.parameters = new LinkedHashMap<>(); + } + this.parameters.put(key, parametersItem); + return this; + } + + /** + * returns the requestBodies property from a Components instance. + * + * @return Map<String, RequestBody> requestBodies + **/ + public Map getRequestBodies() { + return requestBodies; + } + + public void setRequestBodies(Map requestBodies) { + this.requestBodies = requestBodies; + } + + public Components requestBodies(Map requestBodies) { + this.requestBodies = requestBodies; + return this; + } + + public Components addRequestBodies(String key, RequestBody requestBodiesItem) { + if (this.requestBodies == null) { + this.requestBodies = new LinkedHashMap<>(); + } + this.requestBodies.put(key, requestBodiesItem); + return this; + } + + /** + * returns the headers property from a Components instance. + * + * @return Map<String, Header> headers + **/ + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public Components headers(Map headers) { + this.headers = headers; + return this; + } + + public Components addHeaders(String key, Header headersItem) { + if (this.headers == null) { + this.headers = new LinkedHashMap<>(); + } + this.headers.put(key, headersItem); + return this; + } + + /** + * returns the path items property from a Components instance. + * + * @since 2.2.0 (OpenAPI 3.1.0) + * @return Map<String, PathItem> pathItems + **/ + @OpenAPI31 + public Map getPathItems() { + return pathItems; + } + + @OpenAPI31 + public void setPathItems(Map pathItems) { + this.pathItems = pathItems; + } + + @OpenAPI31 + public Components pathItems(Map pathItems) { + this.pathItems = pathItems; + return this; + } + + @OpenAPI31 + public Components addPathItem(String key, PathItem pathItem) { + if (this.pathItems == null) { + this.pathItems = new LinkedHashMap<>(); + } + this.pathItems.put(key, pathItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Components components = (Components) o; + return Objects.equals(this.schemas, components.schemas) + && Objects.equals(this.responses, components.responses) + && Objects.equals(this.parameters, components.parameters) + && Objects.equals(this.requestBodies, components.requestBodies) + && Objects.equals(this.headers, components.headers) + && Objects.equals(this.extensions, components.extensions) + && Objects.equals(this.pathItems, components.pathItems); + } + + @Override + public int hashCode() { + return Objects.hash(schemas, responses, parameters, requestBodies, headers, extensions, pathItems); + } + + public Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public Components extensions(Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Components {\n"); + + sb.append(" schemas: ").append(toIndentedString(schemas)).append("\n"); + sb.append(" responses: ").append(toIndentedString(responses)).append("\n"); + sb.append(" parameters: ").append(toIndentedString(parameters)).append("\n"); + sb.append(" requestBodies: ").append(toIndentedString(requestBodies)).append("\n"); + sb.append(" headers: ").append(toIndentedString(headers)).append("\n"); + sb.append(" pathItems: ").append(toIndentedString(pathItems)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/OpenAPI.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/OpenAPI.java new file mode 100644 index 00000000000..299e2e3a8f2 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/OpenAPI.java @@ -0,0 +1,364 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; +import org.apache.dubbo.metadata.swagger.model.info.Info; +import org.apache.dubbo.metadata.swagger.model.media.Schema; +import org.apache.dubbo.metadata.swagger.model.servers.Server; +import org.apache.dubbo.metadata.swagger.model.tags.Tag; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * OpenAPI + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md" + */ +public class OpenAPI { + private String openapi = "3.0.1"; + private Info info = null; + private List servers = null; + private List tags = null; + private Paths paths = null; + private Components components = null; + private Map extensions = null; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String jsonSchemaDialect; + + public OpenAPI() {} + + public OpenAPI(SpecVersion specVersion) { + this.specVersion = specVersion; + } + + private SpecVersion specVersion = SpecVersion.V30; + + public SpecVersion getSpecVersion() { + return this.specVersion; + } + + public void setSpecVersion(SpecVersion specVersion) { + this.specVersion = specVersion; + } + + public OpenAPI specVersion(SpecVersion specVersion) { + this.setSpecVersion(specVersion); + return this; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Map webhooks = null; + + /** + * returns the openapi property from a OpenAPI instance. + * + * @return String openapi + **/ + public String getOpenapi() { + return openapi; + } + + public void setOpenapi(String openapi) { + this.openapi = openapi; + } + + public OpenAPI openapi(String openapi) { + this.openapi = openapi; + return this; + } + + /** + * returns the info property from a OpenAPI instance. + * + * @return Info info + **/ + public Info getInfo() { + return info; + } + + public void setInfo(Info info) { + this.info = info; + } + + public OpenAPI info(Info info) { + this.info = info; + return this; + } + + /** + * Servers defined in the API + * + * @return List<Server> servers + **/ + public List getServers() { + return servers; + } + + public void setServers(List servers) { + this.servers = servers; + } + + public OpenAPI servers(List servers) { + this.servers = servers; + return this; + } + + public OpenAPI addServersItem(Server serversItem) { + if (this.servers == null) { + this.servers = new ArrayList<>(); + } + this.servers.add(serversItem); + return this; + } + + /** + * returns the tags property from a OpenAPI instance. + * + * @return List<Tag> tags + **/ + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public OpenAPI tags(List tags) { + this.tags = tags; + return this; + } + + public OpenAPI addTagsItem(Tag tagsItem) { + if (this.tags == null) { + this.tags = new ArrayList<>(); + } + this.tags.add(tagsItem); + return this; + } + + /** + * returns the paths property from a OpenAPI instance. + * + * @return Paths paths + **/ + public Paths getPaths() { + return paths; + } + + public void setPaths(Paths paths) { + this.paths = paths; + } + + public OpenAPI paths(Paths paths) { + this.paths = paths; + return this; + } + + /** + * returns the components property from a OpenAPI instance. + * + * @return Components components + **/ + public Components getComponents() { + return components; + } + + public void setComponents(Components components) { + this.components = components; + } + + public OpenAPI components(Components components) { + this.components = components; + return this; + } + + /* + * helpers + */ + + public OpenAPI path(String name, PathItem path) { + if (this.paths == null) { + this.paths = new Paths(); + } + + this.paths.addPathItem(name, path); + return this; + } + + public OpenAPI schema(String name, Schema schema) { + if (components == null) { + this.components = new Components(); + } + components.addSchemas(name, schema); + return this; + } + + /** + * returns the webhooks property from a OpenAPI instance. + * + * @since 2.2.0 (OpenAPI 3.1.0) + * @return Map<String, PathItem> webhooks + **/ + @OpenAPI31 + public Map getWebhooks() { + return webhooks; + } + + @OpenAPI31 + public void setWebhooks(Map webhooks) { + this.webhooks = webhooks; + } + + @OpenAPI31 + public OpenAPI webhooks(Map webhooks) { + this.webhooks = webhooks; + return this; + } + + @OpenAPI31 + public OpenAPI addWebhooks(String key, PathItem pathItem) { + if (this.webhooks == null) { + this.webhooks = new LinkedHashMap<>(); + } + this.webhooks.put(key, pathItem); + return this; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public String getJsonSchemaDialect() { + return jsonSchemaDialect; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setJsonSchemaDialect(String jsonSchemaDialect) { + this.jsonSchemaDialect = jsonSchemaDialect; + } + + @OpenAPI31 + public OpenAPI jsonSchemaDialect(String jsonSchemaDialect) { + this.jsonSchemaDialect = jsonSchemaDialect; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OpenAPI openAPI = (OpenAPI) o; + return Objects.equals(this.openapi, openAPI.openapi) + && Objects.equals(this.info, openAPI.info) + && Objects.equals(this.servers, openAPI.servers) + && Objects.equals(this.tags, openAPI.tags) + && Objects.equals(this.paths, openAPI.paths) + && Objects.equals(this.components, openAPI.components) + && Objects.equals(this.webhooks, openAPI.webhooks) + && Objects.equals(this.extensions, openAPI.extensions) + && Objects.equals(this.jsonSchemaDialect, openAPI.jsonSchemaDialect); + } + + @Override + public int hashCode() { + return Objects.hash(openapi, info, servers, tags, paths, components, webhooks, extensions, jsonSchemaDialect); + } + + public Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public OpenAPI extensions(Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OpenAPI {\n"); + + sb.append(" openapi: ").append(toIndentedString(openapi)).append("\n"); + sb.append(" info: ").append(toIndentedString(info)).append("\n"); + sb.append(" servers: ").append(toIndentedString(servers)).append("\n"); + sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); + sb.append(" paths: ").append(toIndentedString(paths)).append("\n"); + sb.append(" components: ").append(toIndentedString(components)).append("\n"); + if (specVersion == SpecVersion.V31) + sb.append(" webhooks: ").append(toIndentedString(webhooks)).append("\n"); + if (specVersion == SpecVersion.V31) + sb.append(" jsonSchemaDialect: ") + .append(toIndentedString(jsonSchemaDialect)) + .append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Operation.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Operation.java new file mode 100644 index 00000000000..1c7658670a6 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Operation.java @@ -0,0 +1,330 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; +import org.apache.dubbo.metadata.swagger.model.parameters.Parameter; +import org.apache.dubbo.metadata.swagger.model.parameters.RequestBody; +import org.apache.dubbo.metadata.swagger.model.responses.ApiResponses; +import org.apache.dubbo.metadata.swagger.model.servers.Server; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Operation + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#operationObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#operationObject" + */ +public class Operation { + private List tags = null; + private String summary = null; + private String description = null; + private String operationId = null; + private List parameters = null; + private RequestBody requestBody = null; + private ApiResponses responses = null; + private Boolean deprecated = null; + private List servers = null; + private Map extensions = null; + + /** + * returns the tags property from a Operation instance. + * + * @return List<String> tags + **/ + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public Operation tags(List tags) { + this.tags = tags; + return this; + } + + public Operation addTagsItem(String tagsItem) { + if (this.tags == null) { + this.tags = new ArrayList<>(); + } + this.tags.add(tagsItem); + return this; + } + + /** + * returns the summary property from a Operation instance. + * + * @return String summary + **/ + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + public Operation summary(String summary) { + this.summary = summary; + return this; + } + + /** + * returns the description property from a Operation instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Operation description(String description) { + this.description = description; + return this; + } + + /** + * returns the operationId property from a Operation instance. + * + * @return String operationId + **/ + public String getOperationId() { + return operationId; + } + + public void setOperationId(String operationId) { + this.operationId = operationId; + } + + public Operation operationId(String operationId) { + this.operationId = operationId; + return this; + } + + /** + * returns the parameters property from a Operation instance. + * + * @return List<Parameter> parameters + **/ + public List getParameters() { + return parameters; + } + + public void setParameters(List parameters) { + this.parameters = parameters; + } + + public Operation parameters(List parameters) { + this.parameters = parameters; + return this; + } + + public Operation addParametersItem(Parameter parametersItem) { + if (this.parameters == null) { + this.parameters = new ArrayList<>(); + } + this.parameters.add(parametersItem); + return this; + } + + /** + * returns the requestBody property from a Operation instance. + * + * @return RequestBody requestBody + **/ + public RequestBody getRequestBody() { + return requestBody; + } + + public void setRequestBody(RequestBody requestBody) { + this.requestBody = requestBody; + } + + public Operation requestBody(RequestBody requestBody) { + this.requestBody = requestBody; + return this; + } + + /** + * returns the responses property from a Operation instance. + * + * @return ApiResponses responses + **/ + public ApiResponses getResponses() { + return responses; + } + + public void setResponses(ApiResponses responses) { + this.responses = responses; + } + + public Operation responses(ApiResponses responses) { + this.responses = responses; + return this; + } + + /** + * returns the deprecated property from a Operation instance. + * + * @return Boolean deprecated + **/ + public Boolean getDeprecated() { + return deprecated; + } + + public void setDeprecated(Boolean deprecated) { + this.deprecated = deprecated; + } + + public Operation deprecated(Boolean deprecated) { + this.deprecated = deprecated; + return this; + } + + /** + * returns the servers property from a Operation instance. + * + * @return List<Server> servers + **/ + public List getServers() { + return servers; + } + + public void setServers(List servers) { + this.servers = servers; + } + + public Operation servers(List servers) { + this.servers = servers; + return this; + } + + public Operation addServersItem(Server serversItem) { + if (this.servers == null) { + this.servers = new ArrayList<>(); + } + this.servers.add(serversItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Operation operation = (Operation) o; + return Objects.equals(this.tags, operation.tags) + && Objects.equals(this.summary, operation.summary) + && Objects.equals(this.description, operation.description) + && Objects.equals(this.operationId, operation.operationId) + && Objects.equals(this.parameters, operation.parameters) + && Objects.equals(this.requestBody, operation.requestBody) + && Objects.equals(this.responses, operation.responses) + && Objects.equals(this.deprecated, operation.deprecated) + && Objects.equals(this.servers, operation.servers) + && Objects.equals(this.extensions, operation.extensions); + } + + @Override + public int hashCode() { + return Objects.hash( + tags, + summary, + description, + operationId, + parameters, + requestBody, + responses, + deprecated, + servers, + extensions); + } + + public Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public Operation extensions(Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Operation {\n"); + + sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); + sb.append(" summary: ").append(toIndentedString(summary)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" operationId: ").append(toIndentedString(operationId)).append("\n"); + sb.append(" parameters: ").append(toIndentedString(parameters)).append("\n"); + sb.append(" requestBody: ").append(toIndentedString(requestBody)).append("\n"); + sb.append(" responses: ").append(toIndentedString(responses)).append("\n"); + sb.append(" deprecated: ").append(toIndentedString(deprecated)).append("\n"); + sb.append(" servers: ").append(toIndentedString(servers)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/OperationService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/OperationService.java new file mode 100644 index 00000000000..9e169b74180 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/OperationService.java @@ -0,0 +1,87 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; + +public class OperationService { + + public String getOperationId(String operationId, String oldOperationId, OpenAPI openAPI) { + if (StringUtils.isNotBlank(oldOperationId)) return this.getOperationId(oldOperationId, openAPI); + else return this.getOperationId(operationId, openAPI); + } + + public String getOperationId(String operationId, OpenAPI openAPI) { + boolean operationIdUsed = this.existOperationId(operationId, openAPI); + String operationIdToFind = null; + int counter = 0; + while (operationIdUsed) { + operationIdToFind = String.format("%s_%d", operationId, ++counter); + operationIdUsed = this.existOperationId(operationIdToFind, openAPI); + } + if (operationIdToFind != null) { + operationId = operationIdToFind; + } + return operationId; + } + + private boolean existOperationId(String operationId, OpenAPI openAPI) { + if (openAPI == null) { + return false; + } + if (openAPI.getPaths() == null || openAPI.getPaths().isEmpty()) { + return false; + } + for (PathItem path : openAPI.getPaths().values()) { + Set pathOperationIds = this.extractOperationIdFromPathItem(path); + if (pathOperationIds.contains(operationId)) { + return true; + } + } + return false; + } + + private Set extractOperationIdFromPathItem(PathItem path) { + Set ids = new HashSet<>(); + if (path.getGet() != null && StringUtils.isNotBlank(path.getGet().getOperationId())) { + ids.add(path.getGet().getOperationId()); + } + if (path.getPost() != null && StringUtils.isNotBlank(path.getPost().getOperationId())) { + ids.add(path.getPost().getOperationId()); + } + if (path.getPut() != null && StringUtils.isNotBlank(path.getPut().getOperationId())) { + ids.add(path.getPut().getOperationId()); + } + if (path.getDelete() != null && StringUtils.isNotBlank(path.getDelete().getOperationId())) { + ids.add(path.getDelete().getOperationId()); + } + if (path.getOptions() != null + && StringUtils.isNotBlank(path.getOptions().getOperationId())) { + ids.add(path.getOptions().getOperationId()); + } + if (path.getHead() != null && StringUtils.isNotBlank(path.getHead().getOperationId())) { + ids.add(path.getHead().getOperationId()); + } + if (path.getPatch() != null && StringUtils.isNotBlank(path.getPatch().getOperationId())) { + ids.add(path.getPatch().getOperationId()); + } + return ids; + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/PathItem.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/PathItem.java new file mode 100644 index 00000000000..fd63851402f --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/PathItem.java @@ -0,0 +1,536 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; +import org.apache.dubbo.metadata.swagger.model.parameters.Parameter; +import org.apache.dubbo.metadata.swagger.model.servers.Server; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * PathItem + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#pathItemObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#pathItemObject" + */ +public class PathItem { + private String summary = null; + private String description = null; + private Operation get = null; + private Operation put = null; + private Operation post = null; + private Operation delete = null; + private Operation options = null; + private Operation head = null; + private Operation patch = null; + private Operation trace = null; + private List servers = null; + private List parameters = null; + private String $ref = null; + private Map extensions = null; + + /** + * returns the summary property from a PathItem instance. + * + * @return String summary + **/ + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + public PathItem summary(String summary) { + this.summary = summary; + return this; + } + + /** + * returns the description property from a PathItem instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public PathItem description(String description) { + this.description = description; + return this; + } + + /** + * returns the get property from a PathItem instance. + * + * @return Operation get + **/ + public Operation getGet() { + return get; + } + + public void setGet(Operation get) { + this.get = get; + } + + public PathItem get(Operation get) { + this.get = get; + return this; + } + + /** + * returns the put property from a PathItem instance. + * + * @return Operation put + **/ + public Operation getPut() { + return put; + } + + public void setPut(Operation put) { + this.put = put; + } + + public PathItem put(Operation put) { + this.put = put; + return this; + } + + /** + * returns the post property from a PathItem instance. + * + * @return Operation post + **/ + public Operation getPost() { + return post; + } + + public void setPost(Operation post) { + this.post = post; + } + + public PathItem post(Operation post) { + this.post = post; + return this; + } + + /** + * returns the delete property from a PathItem instance. + * + * @return Operation delete + **/ + public Operation getDelete() { + return delete; + } + + public void setDelete(Operation delete) { + this.delete = delete; + } + + public PathItem delete(Operation delete) { + this.delete = delete; + return this; + } + + /** + * returns the options property from a PathItem instance. + * + * @return Operation options + **/ + public Operation getOptions() { + return options; + } + + public void setOptions(Operation options) { + this.options = options; + } + + public PathItem options(Operation options) { + this.options = options; + return this; + } + + /** + * returns the head property from a PathItem instance. + * + * @return Operation head + **/ + public Operation getHead() { + return head; + } + + public void setHead(Operation head) { + this.head = head; + } + + public PathItem head(Operation head) { + this.head = head; + return this; + } + + /** + * returns the patch property from a PathItem instance. + * + * @return Operation patch + **/ + public Operation getPatch() { + return patch; + } + + public void setPatch(Operation patch) { + this.patch = patch; + } + + public PathItem patch(Operation patch) { + this.patch = patch; + return this; + } + + /** + * returns the trace property from a PathItem instance. + * + * @return Operation trace + **/ + public Operation getTrace() { + return trace; + } + + public void setTrace(Operation trace) { + this.trace = trace; + } + + public PathItem trace(Operation trace) { + this.trace = trace; + return this; + } + + public List readOperations() { + List allOperations = new ArrayList<>(); + if (this.get != null) { + allOperations.add(this.get); + } + if (this.put != null) { + allOperations.add(this.put); + } + if (this.head != null) { + allOperations.add(this.head); + } + if (this.post != null) { + allOperations.add(this.post); + } + if (this.delete != null) { + allOperations.add(this.delete); + } + if (this.patch != null) { + allOperations.add(this.patch); + } + if (this.options != null) { + allOperations.add(this.options); + } + if (this.trace != null) { + allOperations.add(this.trace); + } + + return allOperations; + } + + public void operation(HttpMethod method, Operation operation) { + switch (method) { + case PATCH: + this.patch = operation; + break; + case POST: + this.post = operation; + break; + case PUT: + this.put = operation; + break; + case GET: + this.get = operation; + break; + case OPTIONS: + this.options = operation; + break; + case TRACE: + this.trace = operation; + break; + case HEAD: + this.head = operation; + break; + case DELETE: + this.delete = operation; + break; + default: + } + } + + public enum HttpMethod { + POST, + GET, + PUT, + PATCH, + DELETE, + HEAD, + OPTIONS, + TRACE + } + + public Map readOperationsMap() { + Map result = new LinkedHashMap<>(); + + if (this.get != null) { + result.put(HttpMethod.GET, this.get); + } + if (this.put != null) { + result.put(HttpMethod.PUT, this.put); + } + if (this.post != null) { + result.put(HttpMethod.POST, this.post); + } + if (this.delete != null) { + result.put(HttpMethod.DELETE, this.delete); + } + if (this.patch != null) { + result.put(HttpMethod.PATCH, this.patch); + } + if (this.head != null) { + result.put(HttpMethod.HEAD, this.head); + } + if (this.options != null) { + result.put(HttpMethod.OPTIONS, this.options); + } + if (this.trace != null) { + result.put(HttpMethod.TRACE, this.trace); + } + + return result; + } + + /** + * returns the servers property from a PathItem instance. + * + * @return List<Server> servers + **/ + public List getServers() { + return servers; + } + + public void setServers(List servers) { + this.servers = servers; + } + + public PathItem servers(List servers) { + this.servers = servers; + return this; + } + + public PathItem addServersItem(Server serversItem) { + if (this.servers == null) { + this.servers = new ArrayList<>(); + } + this.servers.add(serversItem); + return this; + } + + /** + * returns the parameters property from a PathItem instance. + * + * @return List<Parameter> parameters + **/ + public List getParameters() { + return parameters; + } + + public void setParameters(List parameters) { + this.parameters = parameters; + } + + public PathItem parameters(List parameters) { + this.parameters = parameters; + return this; + } + + public PathItem addParametersItem(Parameter parametersItem) { + if (this.parameters == null) { + this.parameters = new ArrayList<>(); + } + this.parameters.add(parametersItem); + return this; + } + + public Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public PathItem extensions(Map extensions) { + this.extensions = extensions; + return this; + } + + /** + * returns the ref property from a PathItem instance. + * + * @return String ref + **/ + public String get$ref() { + return $ref; + } + + public void set$ref(String $ref) { + this.$ref = $ref; + } + + public PathItem $ref(String $ref) { + set$ref($ref); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof PathItem)) { + return false; + } + + PathItem pathItem = (PathItem) o; + + if (summary != null ? !summary.equals(pathItem.summary) : pathItem.summary != null) { + return false; + } + if (description != null ? !description.equals(pathItem.description) : pathItem.description != null) { + return false; + } + if (get != null ? !get.equals(pathItem.get) : pathItem.get != null) { + return false; + } + if (put != null ? !put.equals(pathItem.put) : pathItem.put != null) { + return false; + } + if (post != null ? !post.equals(pathItem.post) : pathItem.post != null) { + return false; + } + if (delete != null ? !delete.equals(pathItem.delete) : pathItem.delete != null) { + return false; + } + if (options != null ? !options.equals(pathItem.options) : pathItem.options != null) { + return false; + } + if (head != null ? !head.equals(pathItem.head) : pathItem.head != null) { + return false; + } + if (patch != null ? !patch.equals(pathItem.patch) : pathItem.patch != null) { + return false; + } + if (trace != null ? !trace.equals(pathItem.trace) : pathItem.trace != null) { + return false; + } + if (servers != null ? !servers.equals(pathItem.servers) : pathItem.servers != null) { + return false; + } + if (parameters != null ? !parameters.equals(pathItem.parameters) : pathItem.parameters != null) { + return false; + } + if ($ref != null ? !$ref.equals(pathItem.$ref) : pathItem.$ref != null) { + return false; + } + return extensions != null ? extensions.equals(pathItem.extensions) : pathItem.extensions == null; + } + + @Override + public int hashCode() { + int result = summary != null ? summary.hashCode() : 0; + result = 31 * result + (description != null ? description.hashCode() : 0); + result = 31 * result + (get != null ? get.hashCode() : 0); + result = 31 * result + (put != null ? put.hashCode() : 0); + result = 31 * result + (post != null ? post.hashCode() : 0); + result = 31 * result + (delete != null ? delete.hashCode() : 0); + result = 31 * result + (options != null ? options.hashCode() : 0); + result = 31 * result + (head != null ? head.hashCode() : 0); + result = 31 * result + (patch != null ? patch.hashCode() : 0); + result = 31 * result + (trace != null ? trace.hashCode() : 0); + result = 31 * result + (servers != null ? servers.hashCode() : 0); + result = 31 * result + (parameters != null ? parameters.hashCode() : 0); + result = 31 * result + ($ref != null ? $ref.hashCode() : 0); + result = 31 * result + (extensions != null ? extensions.hashCode() : 0); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class PathItem {\n"); + sb.append(" summary: ").append(toIndentedString(summary)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" get: ").append(toIndentedString(get)).append("\n"); + sb.append(" put: ").append(toIndentedString(put)).append("\n"); + sb.append(" post: ").append(toIndentedString(post)).append("\n"); + sb.append(" delete: ").append(toIndentedString(delete)).append("\n"); + sb.append(" options: ").append(toIndentedString(options)).append("\n"); + sb.append(" head: ").append(toIndentedString(head)).append("\n"); + sb.append(" patch: ").append(toIndentedString(patch)).append("\n"); + sb.append(" trace: ").append(toIndentedString(trace)).append("\n"); + sb.append(" servers: ").append(toIndentedString(servers)).append("\n"); + sb.append(" parameters: ").append(toIndentedString(parameters)).append("\n"); + sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Paths.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Paths.java new file mode 100644 index 00000000000..3a112901f2b --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/Paths.java @@ -0,0 +1,107 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; + +import java.util.LinkedHashMap; +import java.util.Objects; + +/** + * Paths + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#pathsObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#pathsObject" + */ +public class Paths extends LinkedHashMap { + public Paths() {} + + private java.util.Map extensions = null; + + public Paths addPathItem(String name, PathItem item) { + this.put(name, item); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Paths paths = (Paths) o; + return Objects.equals(this.extensions, paths.extensions) && super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(extensions, super.hashCode()); + } + + public java.util.Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(java.util.Map extensions) { + this.extensions = extensions; + } + + public Paths extensions(java.util.Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Paths {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/SpecVersion.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/SpecVersion.java new file mode 100644 index 00000000000..b3ef06bd952 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/SpecVersion.java @@ -0,0 +1,22 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model; + +public enum SpecVersion { + V30, + V31 +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/annotations/OpenAPI30.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/annotations/OpenAPI30.java new file mode 100644 index 00000000000..332622cf23f --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/annotations/OpenAPI30.java @@ -0,0 +1,22 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.annotations; + +import java.lang.annotation.Inherited; + +@Inherited +public @interface OpenAPI30 {} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/annotations/OpenAPI31.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/annotations/OpenAPI31.java new file mode 100644 index 00000000000..e39f3b86735 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/annotations/OpenAPI31.java @@ -0,0 +1,22 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.annotations; + +import java.lang.annotation.Inherited; + +@Inherited +public @interface OpenAPI31 {} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/headers/Header.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/headers/Header.java new file mode 100644 index 00000000000..85f5ef80cb3 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/headers/Header.java @@ -0,0 +1,300 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.headers; + +import org.apache.dubbo.metadata.swagger.model.media.Content; +import org.apache.dubbo.metadata.swagger.model.media.Schema; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Header + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#headerObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#headerObject" + */ +public class Header { + private String description = null; + private String $ref = null; + private Boolean required = null; + private Boolean deprecated = null; + + /** + * Gets or Sets style + */ + public enum StyleEnum { + SIMPLE("simple"); + + private String value; + + StyleEnum(String value) { + this.value = value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + private StyleEnum style = null; + private Boolean explode = null; + private Schema schema = null; + private Object example = null; + private Content content = null; + private Map extensions = null; + + /** + * returns the description property from a Header instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Header description(String description) { + this.description = description; + return this; + } + + /** + * returns the required property from a Header instance. + * + * @return Boolean required + **/ + public Boolean getRequired() { + return required; + } + + public void setRequired(Boolean required) { + this.required = required; + } + + public Header required(Boolean required) { + this.required = required; + return this; + } + + /** + * returns the deprecated property from a Header instance. + * + * @return Boolean deprecated + **/ + public Boolean getDeprecated() { + return deprecated; + } + + public void setDeprecated(Boolean deprecated) { + this.deprecated = deprecated; + } + + public Header deprecated(Boolean deprecated) { + this.deprecated = deprecated; + return this; + } + + /** + * returns the style property from a Header instance. + * + * @return StyleEnum style + **/ + public StyleEnum getStyle() { + return style; + } + + public void setStyle(StyleEnum style) { + this.style = style; + } + + public Header style(StyleEnum style) { + this.style = style; + return this; + } + + /** + * returns the explode property from a Header instance. + * + * @return Boolean explode + **/ + public Boolean getExplode() { + return explode; + } + + public void setExplode(Boolean explode) { + this.explode = explode; + } + + public Header explode(Boolean explode) { + this.explode = explode; + return this; + } + + /** + * returns the schema property from a Header instance. + * + * @return Schema schema + **/ + public Schema getSchema() { + return schema; + } + + public void setSchema(Schema schema) { + this.schema = schema; + } + + public Header schema(Schema schema) { + this.schema = schema; + return this; + } + + /** + * returns the example property from a Header instance. + * + * @return String example + **/ + public Object getExample() { + return example; + } + + public void setExample(Object example) { + this.example = example; + } + + public Header example(Object example) { + this.example = example; + return this; + } + + /** + * returns the content property from a Header instance. + * + * @return Content content + **/ + public Content getContent() { + return content; + } + + public void setContent(Content content) { + this.content = content; + } + + public Header content(Content content) { + this.content = content; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Header header = (Header) o; + return Objects.equals(this.description, header.description) + && Objects.equals(this.required, header.required) + && Objects.equals(this.deprecated, header.deprecated) + && Objects.equals(this.style, header.style) + && Objects.equals(this.explode, header.explode) + && Objects.equals(this.schema, header.schema) + && Objects.equals(this.example, header.example) + && Objects.equals(this.content, header.content) + && Objects.equals(this.extensions, header.extensions) + && Objects.equals(this.$ref, header.$ref); + } + + @Override + public int hashCode() { + return Objects.hash( + description, required, deprecated, style, explode, schema, example, content, extensions, $ref); + } + + public Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public Header extensions(Map extensions) { + this.extensions = extensions; + return this; + } + + public String get$ref() { + return $ref; + } + + public void set$ref(String $ref) { + if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { + $ref = "#/components/headers/" + $ref; + } + this.$ref = $ref; + } + + public Header $ref(String $ref) { + set$ref($ref); + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Header {\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" required: ").append(toIndentedString(required)).append("\n"); + sb.append(" deprecated: ").append(toIndentedString(deprecated)).append("\n"); + sb.append(" style: ").append(toIndentedString(style)).append("\n"); + sb.append(" explode: ").append(toIndentedString(explode)).append("\n"); + sb.append(" schema: ").append(toIndentedString(schema)).append("\n"); + sb.append(" example: ").append(toIndentedString(example)).append("\n"); + sb.append(" content: ").append(toIndentedString(content)).append("\n"); + sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/info/Info.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/info/Info.java new file mode 100644 index 00000000000..945957637ee --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/info/Info.java @@ -0,0 +1,219 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.info; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; + +import java.util.Objects; + +/** + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#infoObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#infoObject" + */ +public class Info { + private String title = null; + private String description = null; + private String termsOfService = null; + private String version = null; + private java.util.Map extensions = null; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String summary = null; + + /** + * returns the title property from a Info instance. + * + * @return String title + **/ + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Info title(String title) { + this.title = title; + return this; + } + + /** + * returns the description property from a Info instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Info description(String description) { + this.description = description; + return this; + } + + /** + * returns the termsOfService property from a Info instance. + * + * @return String termsOfService + **/ + public String getTermsOfService() { + return termsOfService; + } + + public void setTermsOfService(String termsOfService) { + this.termsOfService = termsOfService; + } + + public Info termsOfService(String termsOfService) { + this.termsOfService = termsOfService; + return this; + } + + /** + * returns the version property from a Info instance. + * + * @return String version + **/ + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public Info version(String version) { + this.version = version; + return this; + } + + /** + * returns the summary property from a Info instance. + * + * @since 2.2.0 (OpenAPI 3.1.0) + * @return String + **/ + @OpenAPI31 + public String getSummary() { + return summary; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setSummary(String summary) { + this.summary = summary; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Info summary(String summary) { + this.summary = summary; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Info info = (Info) o; + return Objects.equals(this.title, info.title) + && Objects.equals(this.description, info.description) + && Objects.equals(this.termsOfService, info.termsOfService) + && Objects.equals(this.version, info.version) + && Objects.equals(this.extensions, info.extensions) + && Objects.equals(this.summary, info.summary); + } + + @Override + public int hashCode() { + return Objects.hash(title, description, termsOfService, version, extensions, summary); + } + + public java.util.Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new java.util.LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(java.util.Map extensions) { + this.extensions = extensions; + } + + public Info extensions(java.util.Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Info {\n"); + + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" summary: ").append(toIndentedString(summary)).append("\n"); + sb.append(" termsOfService: ") + .append(toIndentedString(termsOfService)) + .append("\n"); + sb.append(" version: ").append(toIndentedString(version)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ArraySchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ArraySchema.java new file mode 100644 index 00000000000..0982510f00c --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ArraySchema.java @@ -0,0 +1,48 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +/** + * ArraySchema + */ +public class ArraySchema extends Schema { + + public ArraySchema() { + super("array", null); + } + + @Override + public ArraySchema type(String type) { + super.setType(type); + return this; + } + + @Override + public ArraySchema items(Schema items) { + super.setItems(items); + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ArraySchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/BinarySchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/BinarySchema.java new file mode 100644 index 00000000000..cfd6fec066c --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/BinarySchema.java @@ -0,0 +1,110 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.Base64; +import java.util.List; +import java.util.Objects; + +/** + * BinarySchema + */ +public class BinarySchema extends Schema { + + public BinarySchema() { + super("string", "binary"); + } + + @Override + public BinarySchema type(String type) { + super.setType(type); + return this; + } + + @Override + public BinarySchema format(String format) { + super.setFormat(format); + return this; + } + + public BinarySchema _default(byte[] _default) { + super.setDefault(_default); + return this; + } + + @Override + protected byte[] cast(Object value) { + if (value != null) { + try { + if (value instanceof byte[]) { + return (byte[]) value; + } else if (value instanceof String) { + if ((System.getProperty(BINARY_STRING_CONVERSION_PROPERTY) != null + && System.getProperty(BINARY_STRING_CONVERSION_PROPERTY) + .equals(BynaryStringConversion.BINARY_STRING_CONVERSION_BASE64.toString())) + || (System.getenv(BINARY_STRING_CONVERSION_PROPERTY) != null + && System.getenv(BINARY_STRING_CONVERSION_PROPERTY) + .equals( + BynaryStringConversion.BINARY_STRING_CONVERSION_BASE64 + .toString()))) { + return Base64.getDecoder().decode((String) value); + } + return value.toString().getBytes(); + } else { + return value.toString().getBytes(); + } + } catch (Exception e) { + } + } + return null; + } + + public BinarySchema _enum(List _enum) { + super.setEnum(_enum); + return this; + } + + public BinarySchema addEnumItem(byte[] _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(_default, _enum, super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class BinarySchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/BooleanSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/BooleanSchema.java new file mode 100644 index 00000000000..9c14280288c --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/BooleanSchema.java @@ -0,0 +1,98 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * BooleanSchema + */ +public class BooleanSchema extends Schema { + + public BooleanSchema() { + super("boolean", null); + } + + @Override + public BooleanSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public BooleanSchema types(Set types) { + super.setTypes(types); + return this; + } + + public BooleanSchema _default(Boolean _default) { + super.setDefault(_default); + return this; + } + + @Override + protected Boolean cast(Object value) { + if (value != null) { + try { + return Boolean.parseBoolean(value.toString()); + } catch (Exception e) { + } + } + return null; + } + + public BooleanSchema _enum(List _enum) { + this._enum = _enum; + return this; + } + + public BooleanSchema addEnumItem(Boolean _enumItem) { + if (this._enum == null) { + this._enum = new ArrayList(); + } + this._enum.add(_enumItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class BooleanSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ByteArraySchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ByteArraySchema.java new file mode 100644 index 00000000000..aae2041387b --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ByteArraySchema.java @@ -0,0 +1,110 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.Base64; +import java.util.List; +import java.util.Objects; + +/** + * ByteArraySchema + */ +public class ByteArraySchema extends Schema { + + public ByteArraySchema() { + super("string", "byte"); + } + + @Override + public ByteArraySchema type(String type) { + super.setType(type); + return this; + } + + @Override + public ByteArraySchema format(String format) { + super.setFormat(format); + return this; + } + + public ByteArraySchema _default(byte[] _default) { + super.setDefault(_default); + return this; + } + + @Override + protected byte[] cast(Object value) { + if (value != null) { + try { + if (value instanceof byte[]) { + return (byte[]) value; + } else if (value instanceof String) { + if ((System.getProperty(BINARY_STRING_CONVERSION_PROPERTY) != null + && System.getProperty(BINARY_STRING_CONVERSION_PROPERTY) + .equals(BynaryStringConversion.BINARY_STRING_CONVERSION_BASE64.toString())) + || (System.getenv(BINARY_STRING_CONVERSION_PROPERTY) != null + && System.getenv(BINARY_STRING_CONVERSION_PROPERTY) + .equals( + BynaryStringConversion.BINARY_STRING_CONVERSION_BASE64 + .toString()))) { + return Base64.getDecoder().decode((String) value); + } + return value.toString().getBytes(); + } else { + return value.toString().getBytes(); + } + } catch (Exception e) { + } + } + return null; + } + + public ByteArraySchema _enum(List _enum) { + super.setEnum(_enum); + return this; + } + + public ByteArraySchema addEnumItem(byte[] _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ByteArraySchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ComposedSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ComposedSchema.java new file mode 100644 index 00000000000..8a47b9e29e7 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ComposedSchema.java @@ -0,0 +1,32 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +/** + * ComposedSchema + */ +public class ComposedSchema extends Schema { + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ComposedSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/Content.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/Content.java new file mode 100644 index 00000000000..704d9e62172 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/Content.java @@ -0,0 +1,70 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.LinkedHashMap; +import java.util.Objects; + +/** + * Content + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#contentObject" + */ +public class Content extends LinkedHashMap { + public Content() {} + + public Content addMediaType(String name, MediaType item) { + this.put(name, item); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Content {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/DateSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/DateSchema.java new file mode 100644 index 00000000000..6f5e009b6f5 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/DateSchema.java @@ -0,0 +1,93 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Objects; + +/** + * DateSchema + */ +public class DateSchema extends Schema { + + public DateSchema() { + super("string", "date"); + } + + @Override + public DateSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public DateSchema format(String format) { + super.setFormat(format); + return this; + } + + public DateSchema _default(Date _default) { + super.setDefault(_default); + return this; + } + + @Override + protected Date cast(Object value) { + if (value != null) { + try { + if (value instanceof Date) { + return (Date) value; + } else if (value instanceof String) { + return new SimpleDateFormat("yyyy-MM-dd Z").parse((String) value + " UTC"); + } + } catch (Exception e) { + } + } + return null; + } + + public DateSchema addEnumItem(Date _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class DateSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/DateTimeSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/DateTimeSchema.java new file mode 100644 index 00000000000..b8451acb138 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/DateTimeSchema.java @@ -0,0 +1,102 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +/** + * DateTimeSchema + */ +public class DateTimeSchema extends Schema { + + public DateTimeSchema() { + super("string", "date-time"); + } + + @Override + public DateTimeSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public DateTimeSchema format(String format) { + super.setFormat(format); + return this; + } + + public DateTimeSchema _default(Date _default) { + super.setDefault(_default); + return this; + } + + @Override + protected OffsetDateTime cast(Object value) { + if (value != null) { + try { + if (value instanceof Date) { + return ((Date) value).toInstant().atOffset(ZoneOffset.UTC); + } else if (value instanceof String) { + return OffsetDateTime.parse((String) value); + } else if (value instanceof OffsetDateTime) { + return (OffsetDateTime) value; + } + } catch (Exception e) { + } + } + return null; + } + + public DateTimeSchema _enum(List _enum) { + super.setEnum(_enum); + return this; + } + + public DateTimeSchema addEnumItem(OffsetDateTime _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class DateTimeSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/EmailSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/EmailSchema.java new file mode 100644 index 00000000000..815694248f5 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/EmailSchema.java @@ -0,0 +1,87 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.Objects; + +/** + * EmailSchema + */ +public class EmailSchema extends Schema { + + public EmailSchema() { + super("string", "email"); + } + + @Override + public EmailSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public EmailSchema format(String format) { + super.setFormat(format); + return this; + } + + public EmailSchema _default(String _default) { + super.setDefault(_default); + return this; + } + + @Override + protected String cast(Object value) { + if (value != null) { + try { + return value.toString(); + } catch (Exception e) { + } + } + return null; + } + + public EmailSchema addEnumItem(String _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class EmailSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/FileSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/FileSchema.java new file mode 100644 index 00000000000..37a2e96cc35 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/FileSchema.java @@ -0,0 +1,66 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.Objects; + +/** + * FileSchema + */ +public class FileSchema extends Schema { + + public FileSchema() { + super("string", "binary"); + } + + @Override + public FileSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public FileSchema format(String format) { + super.setFormat(format); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class FileSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/IntegerSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/IntegerSchema.java new file mode 100644 index 00000000000..51a0af5b11a --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/IntegerSchema.java @@ -0,0 +1,93 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.text.NumberFormat; +import java.util.Objects; + +/** + * IntegerSchema + */ +public class IntegerSchema extends Schema { + + public IntegerSchema() { + super("integer", "int32"); + } + + @Override + public IntegerSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public IntegerSchema format(String format) { + super.setFormat(format); + return this; + } + + public IntegerSchema _default(Number _default) { + super.setDefault(_default); + return this; + } + + @Override + protected Number cast(Object value) { + if (value != null) { + try { + Number casted = NumberFormat.getInstance().parse(value.toString()); + if (Integer.MIN_VALUE <= casted.longValue() && casted.longValue() <= Integer.MAX_VALUE) { + return Integer.parseInt(value.toString()); + } else { + return Long.parseLong(value.toString()); + } + } catch (Exception e) { + } + } + return null; + } + + public IntegerSchema addEnumItem(Number _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class IntegerSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/JsonSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/JsonSchema.java new file mode 100644 index 00000000000..59f6ad81617 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/JsonSchema.java @@ -0,0 +1,38 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import org.apache.dubbo.metadata.swagger.model.SpecVersion; + +/** + * JsonSchema + */ +public class JsonSchema extends Schema { + + public JsonSchema() { + specVersion(SpecVersion.V31); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class JsonSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/MapSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/MapSchema.java new file mode 100644 index 00000000000..5814d73a628 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/MapSchema.java @@ -0,0 +1,60 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.Objects; + +/** + * MapSchema + */ +public class MapSchema extends Schema { + + public MapSchema() { + super("object", null); + } + + @Override + public MapSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class MapSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/MediaType.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/MediaType.java new file mode 100644 index 00000000000..b17db2029fd --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/MediaType.java @@ -0,0 +1,159 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +/** + * MediaType + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#mediaTypeObject" + */ +public class MediaType { + private Schema schema = null; + private Object example = null; + private Map extensions = null; + + private boolean exampleSetFlag; + + /** + * returns the schema property from a MediaType instance. + * + * @return Schema schema + **/ + public Schema getSchema() { + return schema; + } + + public void setSchema(Schema schema) { + this.schema = schema; + } + + public MediaType schema(Schema schema) { + this.schema = schema; + return this; + } + + /** + * returns the example property from a MediaType instance. + * + * @return String example + **/ + public Object getExample() { + return example; + } + + public void setExample(Object example) { + if (this.schema == null) { + this.example = example; + this.exampleSetFlag = true; + return; + } + this.example = this.schema.cast(example); + if (!(example != null && this.example == null)) { + this.exampleSetFlag = true; + } + } + + public MediaType example(Object example) { + setExample(example); + return this; + } + + public boolean getExampleSetFlag() { + return exampleSetFlag; + } + + public void setExampleSetFlag(boolean exampleSetFlag) { + this.exampleSetFlag = exampleSetFlag; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MediaType mediaType = (MediaType) o; + return Objects.equals(this.schema, mediaType.schema) + && Objects.equals(this.example, mediaType.example) + && Objects.equals(this.extensions, mediaType.extensions); + } + + @Override + public int hashCode() { + return Objects.hash(schema, example, extensions); + } + + public Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public MediaType extensions(Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class MediaType {\n"); + + sb.append(" schema: ").append(toIndentedString(schema)).append("\n"); + sb.append(" example: ").append(toIndentedString(example)).append("\n"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/NumberSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/NumberSchema.java new file mode 100644 index 00000000000..c3c0dc65d80 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/NumberSchema.java @@ -0,0 +1,88 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Objects; + +/** + * NumberSchema + */ +public class NumberSchema extends Schema { + + public NumberSchema() { + super("number", null); + } + + @Override + public NumberSchema type(String type) { + super.setType(type); + return this; + } + + public NumberSchema _default(BigDecimal _default) { + super.setDefault(_default); + return this; + } + + public NumberSchema _enum(List _enum) { + super.setEnum(_enum); + return this; + } + + public NumberSchema addEnumItem(BigDecimal _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + protected BigDecimal cast(Object value) { + if (value != null) { + try { + return new BigDecimal(value.toString()); + } catch (Exception e) { + } + } + return null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class NumberSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ObjectSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ObjectSchema.java new file mode 100644 index 00000000000..ae53f9fe13a --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/ObjectSchema.java @@ -0,0 +1,75 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.Objects; + +/** + * ObjectSchema + */ +public class ObjectSchema extends Schema { + + public ObjectSchema() { + super("object", null); + } + + @Override + public ObjectSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public ObjectSchema example(Object example) { + if (example != null) { + super.setExample(example.toString()); + } else { + super.setExample(example); + } + return this; + } + + @Override + protected Object cast(Object value) { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ObjectSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/PasswordSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/PasswordSchema.java new file mode 100644 index 00000000000..518daa4f3e5 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/PasswordSchema.java @@ -0,0 +1,87 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.Objects; + +/** + * PasswordSchema + */ +public class PasswordSchema extends Schema { + + public PasswordSchema() { + super("string", "password"); + } + + @Override + public PasswordSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public PasswordSchema format(String format) { + super.setFormat(format); + return this; + } + + public PasswordSchema _default(String _default) { + super.setDefault(_default); + return this; + } + + @Override + protected String cast(Object value) { + if (value != null) { + try { + return value.toString(); + } catch (Exception e) { + } + } + return null; + } + + public PasswordSchema addEnumItem(String _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class PasswordSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/Schema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/Schema.java new file mode 100644 index 00000000000..966abaa34c3 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/Schema.java @@ -0,0 +1,2294 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import org.apache.dubbo.metadata.swagger.model.SpecVersion; +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI30; +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static org.apache.dubbo.metadata.swagger.model.Components.COMPONENTS_SCHEMAS_REF; + +/** + * Schema + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#schemaObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#schemaObject" + */ +public class Schema { + + public static final String BIND_TYPE_AND_TYPES = "bind-type"; + public static final String BINARY_STRING_CONVERSION_PROPERTY = "binary-string-conversion"; + + public enum BynaryStringConversion { + BINARY_STRING_CONVERSION_BASE64("base64"), + BINARY_STRING_CONVERSION_DEFAULT_CHARSET("default"), + BINARY_STRING_CONVERSION_STRING_SCHEMA("string-schema"); + private String value; + + BynaryStringConversion(String value) { + this.value = value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + public static final String SCHEMA_RESOLUTION_PROPERTY = "schema-resolution"; + + public enum SchemaResolution { + DEFAULT("default"), + INLINE("inline"), + ALL_OF("all-of"), + ALL_OF_REF("all-of-ref"); + + private String value; + + SchemaResolution(String value) { + this.value = value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + protected T _default; + + private String name; + private String title = null; + private BigDecimal multipleOf = null; + private BigDecimal maximum = null; + + @OpenAPI30 + private Boolean exclusiveMaximum = null; + + private BigDecimal minimum = null; + + @OpenAPI30 + private Boolean exclusiveMinimum = null; + + private Integer maxLength = null; + private Integer minLength = null; + private String pattern = null; + private Integer maxItems = null; + private Integer minItems = null; + private Boolean uniqueItems = null; + private Integer maxProperties = null; + private Integer minProperties = null; + private List required = null; + + @OpenAPI30 + private String type = null; + + private Schema not = null; + private Map properties = null; + private Object additionalProperties = null; + private String description = null; + private String format = null; + private String $ref = null; + + @OpenAPI30 + private Boolean nullable = null; + + private Boolean readOnly = null; + private Boolean writeOnly = null; + protected T example = null; + private Boolean deprecated = null; + private Map extensions = null; + protected List _enum = null; + + private boolean exampleSetFlag; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private List prefixItems = null; + + private List allOf = null; + private List anyOf = null; + private List oneOf = null; + + private Schema items = null; + + protected T _const; + + private SpecVersion specVersion = SpecVersion.V30; + + public SpecVersion getSpecVersion() { + return this.specVersion; + } + + public void setSpecVersion(SpecVersion specVersion) { + this.specVersion = specVersion; + } + + public Schema specVersion(SpecVersion specVersion) { + this.setSpecVersion(specVersion); + return this; + } + + /* + @OpenAPI31 fields and accessors + */ + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Set types; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Map patternProperties = null; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private BigDecimal exclusiveMaximumValue = null; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private BigDecimal exclusiveMinimumValue = null; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Schema contains = null; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String $id; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String $schema; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String $anchor; + + /** + * @since 2.2.14 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String $vocabulary; + + /** + * @since 2.2.14 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String $dynamicAnchor; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String contentEncoding; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String contentMediaType; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Schema contentSchema; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Schema propertyNames; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Schema unevaluatedProperties; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Integer maxContains; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Integer minContains; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Schema additionalItems; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Schema unevaluatedItems; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Schema _if; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Schema _else; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Schema then; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Map dependentSchemas; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private Map> dependentRequired; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private String $comment; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + private List examples; + + /** + * @since 2.2.2 (OpenAPI 3.1.0) + * + * when set, this represents a boolean schema value + */ + @OpenAPI31 + private Boolean booleanSchemaValue; + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema getContains() { + return contains; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setContains(Schema contains) { + this.contains = contains; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public String get$id() { + return $id; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void set$id(String $id) { + this.$id = $id; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public String get$schema() { + return $schema; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void set$schema(String $schema) { + this.$schema = $schema; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public String get$anchor() { + return $anchor; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void set$anchor(String $anchor) { + this.$anchor = $anchor; + } + + /** + * returns the exclusiveMaximumValue property from a Schema instance for OpenAPI 3.1.x + * + * @since 2.2.0 (OpenAPI 3.1.0) + * @return BigDecimal exclusiveMaximumValue + * + **/ + @OpenAPI31 + public BigDecimal getExclusiveMaximumValue() { + return exclusiveMaximumValue; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setExclusiveMaximumValue(BigDecimal exclusiveMaximumValue) { + this.exclusiveMaximumValue = exclusiveMaximumValue; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema exclusiveMaximumValue(BigDecimal exclusiveMaximumValue) { + this.exclusiveMaximumValue = exclusiveMaximumValue; + return this; + } + + /** + * returns the exclusiveMinimumValue property from a Schema instance for OpenAPI 3.1.x + * + * @since 2.2.0 (OpenAPI 3.1.0) + * @return BigDecimal exclusiveMinimumValue + * + **/ + @OpenAPI31 + public BigDecimal getExclusiveMinimumValue() { + return exclusiveMinimumValue; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setExclusiveMinimumValue(BigDecimal exclusiveMinimumValue) { + this.exclusiveMinimumValue = exclusiveMinimumValue; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema exclusiveMinimumValue(BigDecimal exclusiveMinimumValue) { + this.exclusiveMinimumValue = exclusiveMinimumValue; + return this; + } + + /** + * returns the patternProperties property from a Schema instance. + * + * @since 2.2.0 (OpenAPI 3.1.0) + * @return Map<String, Schema> patternProperties + **/ + @OpenAPI31 + public Map getPatternProperties() { + return patternProperties; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setPatternProperties(Map patternProperties) { + this.patternProperties = patternProperties; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema patternProperties(Map patternProperties) { + this.patternProperties = patternProperties; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema addPatternProperty(String key, Schema patternPropertiesItem) { + if (this.patternProperties == null) { + this.patternProperties = new LinkedHashMap<>(); + } + this.patternProperties.put(key, patternPropertiesItem); + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema contains(Schema contains) { + this.contains = contains; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema $id(String $id) { + this.$id = $id; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Set getTypes() { + return types; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setTypes(Set types) { + this.types = types; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public boolean addType(String type) { + if (types == null) { + types = new LinkedHashSet<>(); + } + return types.add(type); + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema $schema(String $schema) { + this.$schema = $schema; + return this; + } + + /** + * + * @since 2.2.8 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public String get$vocabulary() { + return $vocabulary; + } + + /** + * + * @since 2.2.8 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void set$vocabulary(String $vocabulary) { + this.$vocabulary = $vocabulary; + } + + /** + * + * @since 2.2.8 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema $vocabulary(String $vocabulary) { + this.$vocabulary = $vocabulary; + return this; + } + + /** + * + * @since 2.2.8 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public String get$dynamicAnchor() { + return $dynamicAnchor; + } + + /** + * + * @since 2.2.8 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void set$dynamicAnchor(String $dynamicAnchor) { + this.$dynamicAnchor = $dynamicAnchor; + } + + /** + * + * @since 2.2.8 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema $dynamicAnchor(String $dynamicAnchor) { + this.$dynamicAnchor = $dynamicAnchor; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema $anchor(String $anchor) { + this.$anchor = $anchor; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema types(Set types) { + this.types = types; + return this; + } + + /* + INTERNAL MEMBERS @OpenAPI31 + */ + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + protected Map jsonSchema = null; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Map getJsonSchema() { + return jsonSchema; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setJsonSchema(Map jsonSchema) { + this.jsonSchema = jsonSchema; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema jsonSchema(Map jsonSchema) { + this.jsonSchema = jsonSchema; + return this; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + protected transient Object jsonSchemaImpl = null; + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Object getJsonSchemaImpl() { + return jsonSchemaImpl; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setJsonSchemaImpl(Object jsonSchemaImpl) { + this.jsonSchemaImpl = jsonSchemaImpl; + } + + /** + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema jsonSchemaImpl(Object jsonSchemaImpl) { + setJsonSchemaImpl(jsonSchemaImpl); + return this; + } + + /* + CONSTRUCTORS + */ + + public Schema() {} + + protected Schema(String type, String format) { + this.type = type; + this.addType(type); + this.format = format; + } + + public Schema(SpecVersion specVersion) { + this.specVersion = specVersion; + } + + protected Schema(String type, String format, SpecVersion specVersion) { + this.type = type; + this.addType(type); + this.format = format; + this.specVersion = specVersion; + } + + /* + ACCESSORS + */ + + /** + * returns the allOf property from a ComposedSchema instance. + * + * @return List<Schema> allOf + **/ + public List getAllOf() { + return allOf; + } + + public void setAllOf(List allOf) { + this.allOf = allOf; + } + + public Schema allOf(List allOf) { + this.allOf = allOf; + return this; + } + + public Schema addAllOfItem(Schema allOfItem) { + if (this.allOf == null) { + this.allOf = new ArrayList<>(); + } + this.allOf.add(allOfItem); + return this; + } + + /** + * returns the anyOf property from a ComposedSchema instance. + * + * @return List<Schema> anyOf + **/ + public List getAnyOf() { + return anyOf; + } + + public void setAnyOf(List anyOf) { + this.anyOf = anyOf; + } + + public Schema anyOf(List anyOf) { + this.anyOf = anyOf; + return this; + } + + public Schema addAnyOfItem(Schema anyOfItem) { + if (this.anyOf == null) { + this.anyOf = new ArrayList<>(); + } + this.anyOf.add(anyOfItem); + return this; + } + + /** + * returns the oneOf property from a ComposedSchema instance. + * + * @return List<Schema> oneOf + **/ + public List getOneOf() { + return oneOf; + } + + public void setOneOf(List oneOf) { + this.oneOf = oneOf; + } + + public Schema oneOf(List oneOf) { + this.oneOf = oneOf; + return this; + } + + public Schema addOneOfItem(Schema oneOfItem) { + if (this.oneOf == null) { + this.oneOf = new ArrayList<>(); + } + this.oneOf.add(oneOfItem); + return this; + } + + /** + * returns the items property from a ArraySchema instance. + * + * @return Schema items + **/ + public Schema getItems() { + return items; + } + + public void setItems(Schema items) { + this.items = items; + } + + public Schema items(Schema items) { + this.items = items; + return this; + } + + /** + * returns the name property from a from a Schema instance. Ignored in serialization. + * + * @return String name + **/ + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public Schema name(String name) { + this.setName(name); + return this; + } + + /** + * returns the title property from a Schema instance. + * + * @return String title + **/ + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Schema title(String title) { + this.title = title; + return this; + } + + /** + * returns the _default property from a Schema instance. + * + * @return String _default + **/ + public T getDefault() { + return _default; + } + + public void setDefault(Object _default) { + this._default = cast(_default); + } + + @SuppressWarnings("unchecked") + protected T cast(Object value) { + return (T) value; + } + + public List getEnum() { + return _enum; + } + + public void setEnum(List _enum) { + this._enum = _enum; + } + + public void addEnumItemObject(T _enumItem) { + if (this._enum == null) { + this._enum = new ArrayList<>(); + } + this._enum.add(cast(_enumItem)); + } + + /** + * returns the multipleOf property from a Schema instance. + *

+ * minimum: 0 + * + * @return BigDecimal multipleOf + **/ + public BigDecimal getMultipleOf() { + return multipleOf; + } + + public void setMultipleOf(BigDecimal multipleOf) { + this.multipleOf = multipleOf; + } + + public Schema multipleOf(BigDecimal multipleOf) { + this.multipleOf = multipleOf; + return this; + } + + /** + * returns the maximum property from a Schema instance. + * + * @return BigDecimal maximum + **/ + public BigDecimal getMaximum() { + return maximum; + } + + public void setMaximum(BigDecimal maximum) { + this.maximum = maximum; + } + + public Schema maximum(BigDecimal maximum) { + this.maximum = maximum; + return this; + } + + /** + * returns the exclusiveMaximum property from a Schema instance for OpenAPI 3.0.x + * + * @return Boolean exclusiveMaximum + **/ + @OpenAPI30 + public Boolean getExclusiveMaximum() { + return exclusiveMaximum; + } + + @OpenAPI30 + public void setExclusiveMaximum(Boolean exclusiveMaximum) { + this.exclusiveMaximum = exclusiveMaximum; + } + + @OpenAPI30 + public Schema exclusiveMaximum(Boolean exclusiveMaximum) { + this.exclusiveMaximum = exclusiveMaximum; + return this; + } + + /** + * returns the minimum property from a Schema instance. + * + * @return BigDecimal minimum + **/ + public BigDecimal getMinimum() { + return minimum; + } + + public void setMinimum(BigDecimal minimum) { + this.minimum = minimum; + } + + public Schema minimum(BigDecimal minimum) { + this.minimum = minimum; + return this; + } + + /** + * returns the exclusiveMinimum property from a Schema instance for OpenAPI 3.0.x + * + * @return Boolean exclusiveMinimum + **/ + public Boolean getExclusiveMinimum() { + return exclusiveMinimum; + } + + public void setExclusiveMinimum(Boolean exclusiveMinimum) { + this.exclusiveMinimum = exclusiveMinimum; + } + + public Schema exclusiveMinimum(Boolean exclusiveMinimum) { + this.exclusiveMinimum = exclusiveMinimum; + return this; + } + + /** + * returns the maxLength property from a Schema instance. + *

+ * minimum: 0 + * + * @return Integer maxLength + **/ + public Integer getMaxLength() { + return maxLength; + } + + public void setMaxLength(Integer maxLength) { + this.maxLength = maxLength; + } + + public Schema maxLength(Integer maxLength) { + this.maxLength = maxLength; + return this; + } + + /** + * returns the minLength property from a Schema instance. + *

+ * minimum: 0 + * + * @return Integer minLength + **/ + public Integer getMinLength() { + return minLength; + } + + public void setMinLength(Integer minLength) { + this.minLength = minLength; + } + + public Schema minLength(Integer minLength) { + this.minLength = minLength; + return this; + } + + /** + * returns the pattern property from a Schema instance. + * + * @return String pattern + **/ + public String getPattern() { + return pattern; + } + + public void setPattern(String pattern) { + this.pattern = pattern; + } + + public Schema pattern(String pattern) { + this.pattern = pattern; + return this; + } + + /** + * returns the maxItems property from a Schema instance. + *

+ * minimum: 0 + * + * @return Integer maxItems + **/ + public Integer getMaxItems() { + return maxItems; + } + + public void setMaxItems(Integer maxItems) { + this.maxItems = maxItems; + } + + public Schema maxItems(Integer maxItems) { + this.maxItems = maxItems; + return this; + } + + /** + * returns the minItems property from a Schema instance. + *

+ * minimum: 0 + * + * @return Integer minItems + **/ + public Integer getMinItems() { + return minItems; + } + + public void setMinItems(Integer minItems) { + this.minItems = minItems; + } + + public Schema minItems(Integer minItems) { + this.minItems = minItems; + return this; + } + + /** + * returns the uniqueItems property from a Schema instance. + * + * @return Boolean uniqueItems + **/ + public Boolean getUniqueItems() { + return uniqueItems; + } + + public void setUniqueItems(Boolean uniqueItems) { + this.uniqueItems = uniqueItems; + } + + public Schema uniqueItems(Boolean uniqueItems) { + this.uniqueItems = uniqueItems; + return this; + } + + /** + * returns the maxProperties property from a Schema instance. + *

+ * minimum: 0 + * + * @return Integer maxProperties + **/ + public Integer getMaxProperties() { + return maxProperties; + } + + public void setMaxProperties(Integer maxProperties) { + this.maxProperties = maxProperties; + } + + public Schema maxProperties(Integer maxProperties) { + this.maxProperties = maxProperties; + return this; + } + + /** + * returns the minProperties property from a Schema instance. + *

+ * minimum: 0 + * + * @return Integer minProperties + **/ + public Integer getMinProperties() { + return minProperties; + } + + public void setMinProperties(Integer minProperties) { + this.minProperties = minProperties; + } + + public Schema minProperties(Integer minProperties) { + this.minProperties = minProperties; + return this; + } + + /** + * returns the required property from a Schema instance. + * + * @return List<String> required + **/ + public List getRequired() { + return required; + } + + public void setRequired(List required) { + List list = new ArrayList<>(); + if (required != null) { + for (String req : required) { + if (this.properties == null || this.properties.containsKey(req)) { + list.add(req); + } + } + } + Collections.sort(list); + if (list.isEmpty()) { + list = null; + } + this.required = list; + } + + public Schema required(List required) { + this.required = required; + return this; + } + + public Schema addRequiredItem(String requiredItem) { + if (this.required == null) { + this.required = new ArrayList<>(); + } + this.required.add(requiredItem); + Collections.sort(required); + return this; + } + + /** + * returns the type property from a Schema instance. + * + * @return String type + **/ + public String getType() { + boolean bindTypes = Boolean.valueOf(System.getProperty(BIND_TYPE_AND_TYPES, "false")); + if (bindTypes && type == null && types != null && types.size() == 1) { + return types.iterator().next(); + } + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Schema type(String type) { + this.type = type; + return this; + } + + /** + * returns the not property from a Schema instance. + * + * @return Schema not + **/ + public Schema getNot() { + return not; + } + + public void setNot(Schema not) { + this.not = not; + } + + public Schema not(Schema not) { + this.not = not; + return this; + } + + /** + * returns the properties property from a Schema instance. + * + * @return Map<String, Schema> properties + **/ + public Map getProperties() { + return properties; + } + + public void setProperties(Map properties) { + this.properties = properties; + } + + public Schema properties(Map properties) { + this.properties = properties; + return this; + } + + @Deprecated + public Schema addProperties(String key, Schema property) { + return addProperty(key, property); + } + + /** + * + * @since 2.2.0 + */ + public Schema addProperty(String key, Schema property) { + if (this.properties == null) { + this.properties = new LinkedHashMap<>(); + } + this.properties.put(key, property); + return this; + } + + /** + * returns the additionalProperties property from a Schema instance. Can be either a Boolean or a Schema + * + * @return Object additionalProperties + **/ + public Object getAdditionalProperties() { + return additionalProperties; + } + + public void setAdditionalProperties(Object additionalProperties) { + if (additionalProperties != null + && !(additionalProperties instanceof Boolean) + && !(additionalProperties instanceof Schema)) { + throw new IllegalArgumentException("additionalProperties must be either a Boolean or a Schema instance"); + } + this.additionalProperties = additionalProperties; + } + + public Schema additionalProperties(Object additionalProperties) { + setAdditionalProperties(additionalProperties); + return this; + } + + /** + * returns the description property from a Schema instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Schema description(String description) { + this.description = description; + return this; + } + + /** + * returns the format property from a Schema instance. + * + * @return String format + **/ + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public Schema format(String format) { + this.format = format; + return this; + } + + /** + * returns the $ref property from a Schema instance. + * + * @return String $ref + **/ + public String get$ref() { + return $ref; + } + + public void set$ref(String $ref) { + if ($ref != null && !$ref.startsWith("#") && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { + $ref = COMPONENTS_SCHEMAS_REF + $ref; + } + this.$ref = $ref; + } + + public Schema $ref(String $ref) { + + set$ref($ref); + return this; + } + + public Schema raw$ref(String $ref) { + this.$ref = $ref; + return this; + } + + /** + * returns the nullable property from a Schema instance. + * + * @return Boolean nullable + **/ + @OpenAPI30 + public Boolean getNullable() { + return nullable; + } + + @OpenAPI30 + public void setNullable(Boolean nullable) { + this.nullable = nullable; + } + + @OpenAPI30 + public Schema nullable(Boolean nullable) { + this.nullable = nullable; + return this; + } + + /** + * returns the readOnly property from a Schema instance. + * + * @return Boolean readOnly + **/ + public Boolean getReadOnly() { + return readOnly; + } + + public void setReadOnly(Boolean readOnly) { + this.readOnly = readOnly; + } + + public Schema readOnly(Boolean readOnly) { + this.readOnly = readOnly; + return this; + } + + /** + * returns the writeOnly property from a Schema instance. + * + * @return Boolean writeOnly + **/ + public Boolean getWriteOnly() { + return writeOnly; + } + + public void setWriteOnly(Boolean writeOnly) { + this.writeOnly = writeOnly; + } + + public Schema writeOnly(Boolean writeOnly) { + this.writeOnly = writeOnly; + return this; + } + + /** + * returns the example property from a Schema instance. + * + * @return String example + **/ + public Object getExample() { + return example; + } + + public void setExample(Object example) { + this.example = cast(example); + if (!(example != null && this.example == null)) { + exampleSetFlag = true; + } + } + + public Schema example(Object example) { + setExample(example); + return this; + } + + /** + * returns the deprecated property from a Schema instance. + * + * @return Boolean deprecated + **/ + public Boolean getDeprecated() { + return deprecated; + } + + public void setDeprecated(Boolean deprecated) { + this.deprecated = deprecated; + } + + public Schema deprecated(Boolean deprecated) { + this.deprecated = deprecated; + return this; + } + + /** + * returns true if example setter has been invoked + * Used to flag explicit setting to null of example (vs missing field) while deserializing from json/yaml string + * + * @return boolean exampleSetFlag + **/ + public boolean getExampleSetFlag() { + return exampleSetFlag; + } + + public void setExampleSetFlag(boolean exampleSetFlag) { + this.exampleSetFlag = exampleSetFlag; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public List getPrefixItems() { + return prefixItems; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setPrefixItems(List prefixItems) { + this.prefixItems = prefixItems; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema prefixItems(List prefixItems) { + this.prefixItems = prefixItems; + return this; + } + + /** + * + * @since 2.2.12 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema addPrefixItem(Schema prefixItem) { + if (this.prefixItems == null) { + this.prefixItems = new ArrayList<>(); + } + this.prefixItems.add(prefixItem); + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public String getContentEncoding() { + return contentEncoding; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setContentEncoding(String contentEncoding) { + this.contentEncoding = contentEncoding; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema contentEncoding(String contentEncoding) { + this.contentEncoding = contentEncoding; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public String getContentMediaType() { + return contentMediaType; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setContentMediaType(String contentMediaType) { + this.contentMediaType = contentMediaType; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema contentMediaType(String contentMediaType) { + this.contentMediaType = contentMediaType; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema getContentSchema() { + return contentSchema; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setContentSchema(Schema contentSchema) { + this.contentSchema = contentSchema; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema contentSchema(Schema contentSchema) { + this.contentSchema = contentSchema; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema getPropertyNames() { + return propertyNames; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setPropertyNames(Schema propertyNames) { + this.propertyNames = propertyNames; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema propertyNames(Schema propertyNames) { + this.propertyNames = propertyNames; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema getUnevaluatedProperties() { + return unevaluatedProperties; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setUnevaluatedProperties(Schema unevaluatedProperties) { + this.unevaluatedProperties = unevaluatedProperties; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema unevaluatedProperties(Schema unevaluatedProperties) { + this.unevaluatedProperties = unevaluatedProperties; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Integer getMaxContains() { + return maxContains; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setMaxContains(Integer maxContains) { + this.maxContains = maxContains; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema maxContains(Integer maxContains) { + this.maxContains = maxContains; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Integer getMinContains() { + return minContains; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setMinContains(Integer minContains) { + this.minContains = minContains; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema minContains(Integer minContains) { + this.minContains = minContains; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema getAdditionalItems() { + return additionalItems; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setAdditionalItems(Schema additionalItems) { + this.additionalItems = additionalItems; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema additionalItems(Schema additionalItems) { + this.additionalItems = additionalItems; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema getUnevaluatedItems() { + return unevaluatedItems; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setUnevaluatedItems(Schema unevaluatedItems) { + this.unevaluatedItems = unevaluatedItems; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema unevaluatedItems(Schema unevaluatedItems) { + this.unevaluatedItems = unevaluatedItems; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema getIf() { + return _if; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setIf(Schema _if) { + this._if = _if; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema _if(Schema _if) { + this._if = _if; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema getElse() { + return _else; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setElse(Schema _else) { + this._else = _else; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema _else(Schema _else) { + this._else = _else; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema getThen() { + return then; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setThen(Schema then) { + this.then = then; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema then(Schema then) { + this.then = then; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Map getDependentSchemas() { + return dependentSchemas; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setDependentSchemas(Map dependentSchemas) { + this.dependentSchemas = dependentSchemas; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema dependentSchemas(Map dependentSchemas) { + this.dependentSchemas = dependentSchemas; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Map> getDependentRequired() { + return dependentRequired; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setDependentRequired(Map> dependentRequired) { + this.dependentRequired = dependentRequired; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema dependentRequired(Map> dependentRequired) { + this.dependentRequired = dependentRequired; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public String get$comment() { + return $comment; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void set$comment(String $comment) { + this.$comment = $comment; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema $comment(String $comment) { + this.$comment = $comment; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public List getExamples() { + return examples; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setExamples(List examples) { + this.examples = examples; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema examples(List examples) { + this.examples = examples; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void addExample(T example) { + if (this.examples == null) { + this.examples = new ArrayList<>(); + } + this.examples.add(example); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Schema schema = (Schema) o; + return Objects.equals(this.title, schema.title) + && Objects.equals(this.multipleOf, schema.multipleOf) + && Objects.equals(this.maximum, schema.maximum) + && Objects.equals(this.exclusiveMaximum, schema.exclusiveMaximum) + && Objects.equals(this.exclusiveMaximumValue, schema.exclusiveMaximumValue) + && Objects.equals(this.minimum, schema.minimum) + && Objects.equals(this.exclusiveMinimum, schema.exclusiveMinimum) + && Objects.equals(this.exclusiveMinimumValue, schema.exclusiveMinimumValue) + && Objects.equals(this.maxLength, schema.maxLength) + && Objects.equals(this.minLength, schema.minLength) + && Objects.equals(this.pattern, schema.pattern) + && Objects.equals(this.maxItems, schema.maxItems) + && Objects.equals(this.minItems, schema.minItems) + && Objects.equals(this.uniqueItems, schema.uniqueItems) + && Objects.equals(this.maxProperties, schema.maxProperties) + && Objects.equals(this.minProperties, schema.minProperties) + && Objects.equals(this.required, schema.required) + && Objects.equals(this.type, schema.type) + && Objects.equals(this.not, schema.not) + && Objects.equals(this.properties, schema.properties) + && Objects.equals(this.additionalProperties, schema.additionalProperties) + && Objects.equals(this.description, schema.description) + && Objects.equals(this.format, schema.format) + && Objects.equals(this.$ref, schema.$ref) + && Objects.equals(this.nullable, schema.nullable) + && Objects.equals(this.readOnly, schema.readOnly) + && Objects.equals(this.writeOnly, schema.writeOnly) + && Objects.equals(this.example, schema.example) + && Objects.equals(this.deprecated, schema.deprecated) + && Objects.equals(this.extensions, schema.extensions) + && Objects.equals(this._enum, schema._enum) + && Objects.equals(this.contains, schema.contains) + && Objects.equals(this.patternProperties, schema.patternProperties) + && Objects.equals(this.$id, schema.$id) + && Objects.equals(this.$anchor, schema.$anchor) + && Objects.equals(this.$schema, schema.$schema) + && Objects.equals(this.$vocabulary, schema.$vocabulary) + && Objects.equals(this.$dynamicAnchor, schema.$dynamicAnchor) + && Objects.equals(this.types, schema.types) + && Objects.equals(this.allOf, schema.allOf) + && Objects.equals(this.anyOf, schema.anyOf) + && Objects.equals(this.oneOf, schema.oneOf) + && Objects.equals(this._const, schema._const) + && Objects.equals(this._default, schema._default) + && Objects.equals(this.contentEncoding, schema.contentEncoding) + && Objects.equals(this.contentMediaType, schema.contentMediaType) + && Objects.equals(this.contentSchema, schema.contentSchema) + && Objects.equals(this.propertyNames, schema.propertyNames) + && Objects.equals(this.unevaluatedProperties, schema.unevaluatedProperties) + && Objects.equals(this.maxContains, schema.maxContains) + && Objects.equals(this.minContains, schema.minContains) + && Objects.equals(this.additionalItems, schema.additionalItems) + && Objects.equals(this.unevaluatedItems, schema.unevaluatedItems) + && Objects.equals(this._if, schema._if) + && Objects.equals(this._else, schema._else) + && Objects.equals(this.then, schema.then) + && Objects.equals(this.dependentRequired, schema.dependentRequired) + && Objects.equals(this.dependentSchemas, schema.dependentSchemas) + && Objects.equals(this.$comment, schema.$comment) + && Objects.equals(this.examples, schema.examples) + && Objects.equals(this.prefixItems, schema.prefixItems) + && Objects.equals(this.items, schema.items); + } + + @Override + public int hashCode() { + return Objects.hash( + title, + multipleOf, + maximum, + exclusiveMaximum, + exclusiveMaximumValue, + minimum, + exclusiveMinimum, + exclusiveMinimumValue, + maxLength, + minLength, + pattern, + maxItems, + minItems, + uniqueItems, + maxProperties, + minProperties, + required, + type, + not, + properties, + additionalProperties, + description, + format, + $ref, + nullable, + readOnly, + writeOnly, + example, + deprecated, + extensions, + _enum, + _default, + patternProperties, + $id, + $anchor, + $schema, + $vocabulary, + $dynamicAnchor, + types, + allOf, + anyOf, + oneOf, + _const, + contentEncoding, + contentMediaType, + contentSchema, + propertyNames, + unevaluatedProperties, + maxContains, + minContains, + additionalItems, + unevaluatedItems, + _if, + _else, + then, + dependentRequired, + dependentSchemas, + $comment, + examples, + prefixItems, + items); + } + + public Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || (specVersion == SpecVersion.V30 && !name.startsWith("x-"))) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public Schema extensions(Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Schema {\n"); + Object typeStr = specVersion == SpecVersion.V30 ? type : types; + sb.append(" type: ").append(toIndentedString(typeStr)).append("\n"); + sb.append(" format: ").append(toIndentedString(format)).append("\n"); + sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" multipleOf: ").append(toIndentedString(multipleOf)).append("\n"); + sb.append(" maximum: ").append(toIndentedString(maximum)).append("\n"); + Object exclusiveMaximumStr = specVersion == SpecVersion.V30 ? exclusiveMaximum : exclusiveMaximumValue; + sb.append(" exclusiveMaximum: ") + .append(toIndentedString(exclusiveMaximumStr)) + .append("\n"); + sb.append(" minimum: ").append(toIndentedString(minimum)).append("\n"); + Object exclusiveMinimumStr = specVersion == SpecVersion.V30 ? exclusiveMinimum : exclusiveMinimumValue; + sb.append(" exclusiveMinimum: ") + .append(toIndentedString(exclusiveMinimumStr)) + .append("\n"); + sb.append(" maxLength: ").append(toIndentedString(maxLength)).append("\n"); + sb.append(" minLength: ").append(toIndentedString(minLength)).append("\n"); + sb.append(" pattern: ").append(toIndentedString(pattern)).append("\n"); + sb.append(" maxItems: ").append(toIndentedString(maxItems)).append("\n"); + sb.append(" minItems: ").append(toIndentedString(minItems)).append("\n"); + sb.append(" uniqueItems: ").append(toIndentedString(uniqueItems)).append("\n"); + sb.append(" maxProperties: ").append(toIndentedString(maxProperties)).append("\n"); + sb.append(" minProperties: ").append(toIndentedString(minProperties)).append("\n"); + sb.append(" required: ").append(toIndentedString(required)).append("\n"); + sb.append(" not: ").append(toIndentedString(not)).append("\n"); + sb.append(" properties: ").append(toIndentedString(properties)).append("\n"); + sb.append(" additionalProperties: ") + .append(toIndentedString(additionalProperties)) + .append("\n"); + sb.append(" nullable: ").append(toIndentedString(nullable)).append("\n"); + sb.append(" readOnly: ").append(toIndentedString(readOnly)).append("\n"); + sb.append(" writeOnly: ").append(toIndentedString(writeOnly)).append("\n"); + sb.append(" example: ").append(toIndentedString(example)).append("\n"); + sb.append(" deprecated: ").append(toIndentedString(deprecated)).append("\n"); + if (specVersion == SpecVersion.V31) { + sb.append(" patternProperties: ") + .append(toIndentedString(patternProperties)) + .append("\n"); + sb.append(" contains: ").append(toIndentedString(contains)).append("\n"); + sb.append(" $id: ").append(toIndentedString($id)).append("\n"); + sb.append(" $anchor: ").append(toIndentedString($anchor)).append("\n"); + sb.append(" $schema: ").append(toIndentedString($schema)).append("\n"); + sb.append(" $vocabulary: ").append(toIndentedString($vocabulary)).append("\n"); + sb.append(" $dynamicAnchor: ") + .append(toIndentedString($dynamicAnchor)) + .append("\n"); + sb.append(" const: ").append(toIndentedString(_const)).append("\n"); + sb.append(" contentEncoding: ") + .append(toIndentedString(contentEncoding)) + .append("\n"); + sb.append(" contentMediaType: ") + .append(toIndentedString(contentMediaType)) + .append("\n"); + sb.append(" contentSchema: ") + .append(toIndentedString(contentSchema)) + .append("\n"); + sb.append(" propertyNames: ") + .append(toIndentedString(propertyNames)) + .append("\n"); + sb.append(" unevaluatedProperties: ") + .append(toIndentedString(unevaluatedProperties)) + .append("\n"); + sb.append(" maxContains: ").append(toIndentedString(maxContains)).append("\n"); + sb.append(" minContains: ").append(toIndentedString(minContains)).append("\n"); + sb.append(" additionalItems: ") + .append(toIndentedString(additionalItems)) + .append("\n"); + sb.append(" unevaluatedItems: ") + .append(toIndentedString(unevaluatedItems)) + .append("\n"); + sb.append(" _if: ").append(toIndentedString(_if)).append("\n"); + sb.append(" _else: ").append(toIndentedString(_else)).append("\n"); + sb.append(" then: ").append(toIndentedString(then)).append("\n"); + sb.append(" dependentRequired: ") + .append(toIndentedString(dependentRequired)) + .append("\n"); + sb.append(" dependentSchemas: ") + .append(toIndentedString(dependentSchemas)) + .append("\n"); + sb.append(" $comment: ").append(toIndentedString($comment)).append("\n"); + sb.append(" prefixItems: ").append(toIndentedString(prefixItems)).append("\n"); + } + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + protected String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public Schema _default(T _default) { + this._default = _default; + return this; + } + + public Schema _enum(List _enum) { + this._enum = _enum; + return this; + } + + public Schema exampleSetFlag(boolean exampleSetFlag) { + this.exampleSetFlag = exampleSetFlag; + return this; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public T getConst() { + return _const; + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setConst(Object _const) { + this._const = cast(_const); + } + + /** + * + * @since 2.2.0 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema _const(Object _const) { + this._const = cast(_const); + return this; + } + + /** + * + * @since 2.2.2 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Boolean getBooleanSchemaValue() { + return booleanSchemaValue; + } + + /** + * + * @since 2.2.2 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public void setBooleanSchemaValue(Boolean booleanSchemaValue) { + this.booleanSchemaValue = booleanSchemaValue; + } + + /** + * + * @since 2.2.2 (OpenAPI 3.1.0) + */ + @OpenAPI31 + public Schema booleanSchemaValue(Boolean booleanSchemaValue) { + this.booleanSchemaValue = booleanSchemaValue; + return this; + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/StringSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/StringSchema.java new file mode 100644 index 00000000000..dd275afa224 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/StringSchema.java @@ -0,0 +1,87 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.List; +import java.util.Objects; + +/** + * StringSchema + */ +public class StringSchema extends Schema { + + public StringSchema() { + super("string", null); + } + + @Override + public StringSchema type(String type) { + super.setType(type); + return this; + } + + public StringSchema _default(String _default) { + super.setDefault(_default); + return this; + } + + public StringSchema _enum(List _enum) { + super.setEnum(_enum); + return this; + } + + public StringSchema addEnumItem(String _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + protected String cast(Object value) { + if (value != null) { + try { + return value.toString(); + } catch (Exception e) { + } + } + return null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class StringSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/UUIDSchema.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/UUIDSchema.java new file mode 100644 index 00000000000..6047e9b05a6 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/media/UUIDSchema.java @@ -0,0 +1,101 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.media; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +/** + * UUIDSchema + */ +public class UUIDSchema extends Schema { + + public UUIDSchema() { + super("string", "uuid"); + } + + @Override + public UUIDSchema type(String type) { + super.setType(type); + return this; + } + + @Override + public UUIDSchema format(String format) { + super.setFormat(format); + return this; + } + + public UUIDSchema _default(UUID _default) { + super.setDefault(_default); + return this; + } + + public UUIDSchema _default(String _default) { + if (_default != null) { + super.setDefault(UUID.fromString(_default)); + } + return this; + } + + public UUIDSchema _enum(List _enum) { + super.setEnum(_enum); + return this; + } + + public UUIDSchema addEnumItem(UUID _enumItem) { + super.addEnumItemObject(_enumItem); + return this; + } + + @Override + protected UUID cast(Object value) { + if (value != null) { + try { + return UUID.fromString(value.toString()); + } catch (Exception e) { + } + } + return null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class UUIDSchema {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/Parameter.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/Parameter.java new file mode 100644 index 00000000000..f6461a64bdf --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/Parameter.java @@ -0,0 +1,418 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.parameters; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; +import org.apache.dubbo.metadata.swagger.model.media.Content; +import org.apache.dubbo.metadata.swagger.model.media.Schema; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Parameter + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#parameterObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#parameterObject" + */ +public class Parameter { + private String name = null; + private String in = null; + private String description = null; + private Boolean required = null; + private Boolean deprecated = null; + private Boolean allowEmptyValue = null; + private String $ref = null; + + /** + * Gets or Sets style + */ + public enum StyleEnum { + MATRIX("matrix"), + LABEL("label"), + FORM("form"), + SIMPLE("simple"), + SPACEDELIMITED("spaceDelimited"), + PIPEDELIMITED("pipeDelimited"), + DEEPOBJECT("deepObject"); + + private String value; + + StyleEnum(String value) { + this.value = value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + private StyleEnum style = null; + private Boolean explode = null; + private Boolean allowReserved = null; + private Schema schema = null; + private Object example = null; + private Content content = null; + private Map extensions = null; + + /** + * returns the name property from a Parameter instance. + * + * @return String name + **/ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Parameter name(String name) { + this.name = name; + return this; + } + + /** + * returns the in property from a Parameter instance. + * + * @return String in + **/ + public String getIn() { + return in; + } + + public void setIn(String in) { + if ("path".equals(in)) { + this.required = true; + } + this.in = in; + } + + public Parameter in(String in) { + setIn(in); + return this; + } + + /** + * returns the description property from a Parameter instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Parameter description(String description) { + this.description = description; + return this; + } + + /** + * returns the required property from a Parameter instance. + * + * @return Boolean required + **/ + public Boolean getRequired() { + return required; + } + + public void setRequired(Boolean required) { + this.required = required; + } + + public Parameter required(Boolean required) { + this.required = required; + return this; + } + + /** + * returns the deprecated property from a Parameter instance. + * + * @return Boolean deprecated + **/ + public Boolean getDeprecated() { + return deprecated; + } + + public void setDeprecated(Boolean deprecated) { + this.deprecated = deprecated; + } + + public Parameter deprecated(Boolean deprecated) { + this.deprecated = deprecated; + return this; + } + + /** + * returns the allowEmptyValue property from a Parameter instance. + * + * @return Boolean allowEmptyValue + **/ + public Boolean getAllowEmptyValue() { + return allowEmptyValue; + } + + public void setAllowEmptyValue(Boolean allowEmptyValue) { + this.allowEmptyValue = allowEmptyValue; + } + + public Parameter allowEmptyValue(Boolean allowEmptyValue) { + this.allowEmptyValue = allowEmptyValue; + return this; + } + + /** + * returns the style property from a Parameter instance. + * + * @return StyleEnum style + **/ + public StyleEnum getStyle() { + return style; + } + + public void setStyle(StyleEnum style) { + this.style = style; + } + + public Parameter style(StyleEnum style) { + this.style = style; + return this; + } + + /** + * returns the explode property from a Parameter instance. + * + * @return Boolean explode + **/ + public Boolean getExplode() { + return explode; + } + + public void setExplode(Boolean explode) { + this.explode = explode; + } + + public Parameter explode(Boolean explode) { + this.explode = explode; + return this; + } + + /** + * returns the allowReserved property from a Parameter instance. + * + * @return Boolean allowReserved + **/ + public Boolean getAllowReserved() { + return allowReserved; + } + + public void setAllowReserved(Boolean allowReserved) { + this.allowReserved = allowReserved; + } + + public Parameter allowReserved(Boolean allowReserved) { + this.allowReserved = allowReserved; + return this; + } + + /** + * returns the schema property from a Parameter instance. + * + * @return Schema schema + **/ + public Schema getSchema() { + return schema; + } + + public void setSchema(Schema schema) { + this.schema = schema; + } + + public Parameter schema(Schema schema) { + this.schema = schema; + return this; + } + + /** + * returns the example property from a Parameter instance. + * + * @return String example + **/ + public Object getExample() { + return example; + } + + public void setExample(Object example) { + this.example = example; + } + + public Parameter example(Object example) { + this.example = example; + return this; + } + + /** + * returns the content property from a Parameter instance. + * + * @return Content content + **/ + public Content getContent() { + return content; + } + + public void setContent(Content content) { + this.content = content; + } + + public Parameter content(Content content) { + this.content = content; + return this; + } + + public String get$ref() { + return $ref; + } + + public void set$ref(String $ref) { + if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { + $ref = "#/components/parameters/" + $ref; + } + this.$ref = $ref; + } + + public Parameter $ref(String $ref) { + set$ref($ref); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Parameter parameter = (Parameter) o; + return Objects.equals(this.name, parameter.name) + && Objects.equals(this.in, parameter.in) + && Objects.equals(this.description, parameter.description) + && Objects.equals(this.required, parameter.required) + && Objects.equals(this.deprecated, parameter.deprecated) + && Objects.equals(this.allowEmptyValue, parameter.allowEmptyValue) + && Objects.equals(this.style, parameter.style) + && Objects.equals(this.explode, parameter.explode) + && Objects.equals(this.allowReserved, parameter.allowReserved) + && Objects.equals(this.schema, parameter.schema) + && Objects.equals(this.example, parameter.example) + && Objects.equals(this.content, parameter.content) + && Objects.equals(this.$ref, parameter.$ref) + && Objects.equals(this.extensions, parameter.extensions); + } + + @Override + public int hashCode() { + return Objects.hash( + name, + in, + description, + required, + deprecated, + allowEmptyValue, + style, + explode, + allowReserved, + schema, + example, + content, + $ref, + extensions); + } + + public Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public Parameter extensions(Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Parameter {\n"); + + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" in: ").append(toIndentedString(in)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" required: ").append(toIndentedString(required)).append("\n"); + sb.append(" deprecated: ").append(toIndentedString(deprecated)).append("\n"); + sb.append(" allowEmptyValue: ") + .append(toIndentedString(allowEmptyValue)) + .append("\n"); + sb.append(" style: ").append(toIndentedString(style)).append("\n"); + sb.append(" explode: ").append(toIndentedString(explode)).append("\n"); + sb.append(" allowReserved: ").append(toIndentedString(allowReserved)).append("\n"); + sb.append(" schema: ").append(toIndentedString(schema)).append("\n"); + sb.append(" example: ").append(toIndentedString(example)).append("\n"); + sb.append(" content: ").append(toIndentedString(content)).append("\n"); + sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + static String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/ParameterId.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/ParameterId.java new file mode 100644 index 00000000000..306276a2d55 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/ParameterId.java @@ -0,0 +1,136 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.parameters; + +import org.apache.dubbo.common.utils.StringUtils; + +import java.util.Objects; + +/** + * The type Parameter Id. + * + * @author bnasslahsen + */ +public class ParameterId { + + /** + * The P name. + */ + private String pName; + + /** + * The Param type. + */ + private String paramType; + + /** + * The Ref. + */ + private String $ref; + + /** + * Instantiates a new Parameter id. + * + * @param parameter the parameter + */ + public ParameterId(Parameter parameter) { + this.pName = parameter.getName(); + this.paramType = parameter.getIn(); + this.$ref = parameter.get$ref(); + } + + /** + * Instantiates a new Parameter id. + * + * @param pName the p name + * @param paramType the param type + */ + public ParameterId(String pName, String paramType) { + this.pName = pName; + this.paramType = paramType; + } + + /** + * Gets name. + * + * @return the name + */ + public String getpName() { + return pName; + } + + /** + * Sets name. + * + * @param pName the p name + */ + public void setpName(String pName) { + this.pName = pName; + } + + /** + * Gets param type. + * + * @return the param type + */ + public String getParamType() { + return paramType; + } + + /** + * Sets param type. + * + * @param paramType the param type + */ + public void setParamType(String paramType) { + this.paramType = paramType; + } + + /** + * Get ref string. + * + * @return the string + */ + public String get$ref() { + return $ref; + } + + /** + * Set ref. + * + * @param $ref the ref + */ + public void set$ref(String $ref) { + this.$ref = $ref; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ParameterId that = (ParameterId) o; + if (this.pName == null && StringUtils.isBlank(this.paramType)) return Objects.equals($ref, that.$ref); + if (this.pName != null && StringUtils.isBlank(this.paramType)) return Objects.equals(pName, that.pName); + + return Objects.equals(pName, that.pName) && Objects.equals(paramType, that.paramType); + } + + @Override + public int hashCode() { + return Objects.hash(pName, paramType, $ref); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/ParameterInfo.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/ParameterInfo.java new file mode 100644 index 00000000000..dc7238e9e17 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/ParameterInfo.java @@ -0,0 +1,117 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.parameters; + +import org.apache.dubbo.metadata.swagger.ParameterService; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ParameterMeta; + +public class ParameterInfo { + + /** + * The Method parameter. + */ + private final ParameterMeta methodParameter; + + /** + * The P name. + */ + private String pName; + + /** + * The Parameter id. + */ + private ParameterId parameterId; + + /** + * The Required. + */ + private boolean required; + + /** + * The Param type. + */ + private String paramType; + + /** + * The Default value. + */ + private Object defaultValue; + + /** + * The Parameter model. + */ + private Parameter parameterModel; + + public Object getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(Object defaultValue) { + this.defaultValue = defaultValue; + } + + public String getParamType() { + return paramType; + } + + public void setParamType(String paramType) { + this.paramType = paramType; + } + + public boolean isRequired() { + return required; + } + + public void setRequired(boolean required) { + this.required = required; + } + + public ParameterId getParameterId() { + return parameterId; + } + + public void setParameterId(ParameterId parameterId) { + this.parameterId = parameterId; + } + + public String getpName() { + return pName; + } + + public void setpName(String pName) { + this.pName = pName; + } + + public ParameterMeta getMethodParameter() { + return methodParameter; + } + + public Parameter getParameterModel() { + return parameterModel; + } + + public void setParameterModel(Parameter parameterModel) { + this.parameterModel = parameterModel; + } + + public ParameterInfo(String pName, ParameterMeta methodParameter, ParameterService parameterService) { + this.methodParameter = methodParameter; + this.pName = pName; + this.required = false; + this.parameterId = new ParameterId(this.pName, paramType); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/RequestBody.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/RequestBody.java new file mode 100644 index 00000000000..ac52c238bff --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/RequestBody.java @@ -0,0 +1,194 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.parameters; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; +import org.apache.dubbo.metadata.swagger.model.media.Content; + +/** + * RequestBody + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#requestBodyObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#requestBodyObject" + */ +public class RequestBody { + private String description = null; + private Content content = null; + private Boolean required = null; + private java.util.Map extensions = null; + private String $ref = null; + + /** + * returns the description property from a RequestBody instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public RequestBody description(String description) { + this.description = description; + return this; + } + + /** + * returns the content property from a RequestBody instance. + * + * @return Content content + **/ + public Content getContent() { + return content; + } + + public void setContent(Content content) { + this.content = content; + } + + public RequestBody content(Content content) { + this.content = content; + return this; + } + + /** + * returns the required property from a RequestBody instance. + * + * @return Boolean required + **/ + public Boolean getRequired() { + return required; + } + + public void setRequired(Boolean required) { + this.required = required; + } + + public RequestBody required(Boolean required) { + this.required = required; + return this; + } + + public java.util.Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new java.util.LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(java.util.Map extensions) { + this.extensions = extensions; + } + + public RequestBody extensions(java.util.Map extensions) { + this.extensions = extensions; + return this; + } + + public String get$ref() { + return $ref; + } + + public void set$ref(String $ref) { + if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { + $ref = "#/components/requestBodies/" + $ref; + } + this.$ref = $ref; + } + + public RequestBody $ref(String $ref) { + set$ref($ref); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof RequestBody)) { + return false; + } + + RequestBody that = (RequestBody) o; + + if (description != null ? !description.equals(that.description) : that.description != null) { + return false; + } + if (content != null ? !content.equals(that.content) : that.content != null) { + return false; + } + if (required != null ? !required.equals(that.required) : that.required != null) { + return false; + } + if (extensions != null ? !extensions.equals(that.extensions) : that.extensions != null) { + return false; + } + return $ref != null ? $ref.equals(that.$ref) : that.$ref == null; + } + + @Override + public int hashCode() { + int result = description != null ? description.hashCode() : 0; + result = 31 * result + (content != null ? content.hashCode() : 0); + result = 31 * result + (required != null ? required.hashCode() : 0); + result = 31 * result + (extensions != null ? extensions.hashCode() : 0); + result = 31 * result + ($ref != null ? $ref.hashCode() : 0); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RequestBody {\n"); + + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" content: ").append(toIndentedString(content)).append("\n"); + sb.append(" required: ").append(toIndentedString(required)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/RequestBodyInfo.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/RequestBodyInfo.java new file mode 100644 index 00000000000..d110245bee3 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/parameters/RequestBodyInfo.java @@ -0,0 +1,75 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.parameters; + +import org.apache.dubbo.metadata.swagger.model.media.Schema; + +public class RequestBodyInfo { + + /** + * The Request body. + */ + private RequestBody requestBody; + + /** + * The Merged schema. + */ + private Schema mergedSchema; + + /** + * Gets request body. + * + * @return the request body + */ + public RequestBody getRequestBody() { + return requestBody; + } + + /** + * Sets request body. + * + * @param requestBody the request body + */ + public void setRequestBody(RequestBody requestBody) { + this.requestBody = requestBody; + } + + /** + * Gets merged schema. + * + * @return the merged schema + */ + public Schema getMergedSchema() { + return mergedSchema; + } + + /** + * Sets merged schema. + * + * @param mergedSchema the merged schema + */ + public void setMergedSchema(Schema mergedSchema) { + this.mergedSchema = mergedSchema; + } + + public void addProperties(String paramName, Schema schemaN) { + if (mergedSchema == null) { + mergedSchema = new Schema(); + } + mergedSchema.addProperty(paramName, schemaN); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/responses/ApiResponse.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/responses/ApiResponse.java new file mode 100644 index 00000000000..c2e3cc9f2e0 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/responses/ApiResponse.java @@ -0,0 +1,199 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.responses; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; +import org.apache.dubbo.metadata.swagger.model.headers.Header; +import org.apache.dubbo.metadata.swagger.model.media.Content; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +/** + * ApiResponse + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#responseObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#responseObject" + */ +public class ApiResponse { + private String description = null; + private Map headers = null; + private Content content = null; + private Map extensions = null; + private String $ref = null; + + /** + * returns the description property from a ApiResponse instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public ApiResponse description(String description) { + this.description = description; + return this; + } + + /** + * returns the headers property from a ApiResponse instance. + * + * @return headers + **/ + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public ApiResponse headers(Map headers) { + this.headers = headers; + return this; + } + + public ApiResponse addHeaderObject(String name, Header header) { + if (this.headers == null) { + headers = new LinkedHashMap<>(); + } + headers.put(name, header); + return this; + } + + /** + * returns the content property from a ApiResponse instance. + * + * @return Content content + **/ + public Content getContent() { + return content; + } + + public void setContent(Content content) { + this.content = content; + } + + public ApiResponse content(Content content) { + this.content = content; + return this; + } + + /** + * returns the $ref property from an ApiResponse instance. + * + * @return String $ref + **/ + public String get$ref() { + return $ref; + } + + public void set$ref(String $ref) { + if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { + $ref = "#/components/responses/" + $ref; + } + this.$ref = $ref; + } + + public ApiResponse $ref(String $ref) { + set$ref($ref); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ApiResponse apiResponse = (ApiResponse) o; + return Objects.equals(this.description, apiResponse.description) + && Objects.equals(this.headers, apiResponse.headers) + && Objects.equals(this.content, apiResponse.content) + && Objects.equals(this.extensions, apiResponse.extensions) + && Objects.equals(this.$ref, apiResponse.$ref); + } + + @Override + public int hashCode() { + return Objects.hash(description, headers, content, extensions, $ref); + } + + public Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public ApiResponse extensions(Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ApiResponse {\n"); + + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" headers: ").append(toIndentedString(headers)).append("\n"); + sb.append(" content: ").append(toIndentedString(content)).append("\n"); + sb.append(" extensions: ").append(toIndentedString(extensions)).append("\n"); + sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/responses/ApiResponses.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/responses/ApiResponses.java new file mode 100644 index 00000000000..53ec974783f --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/responses/ApiResponses.java @@ -0,0 +1,133 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.responses; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; + +import java.util.LinkedHashMap; +import java.util.Objects; + +/** + * ApiResponses + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#responsesObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#responsesObject" + */ +public class ApiResponses extends LinkedHashMap { + + public static final String DEFAULT = "default"; + + private java.util.Map extensions = null; + + public ApiResponses addApiResponse(String name, ApiResponse item) { + this.put(name, item); + return this; + } + + /** + * returns the default property from a ApiResponses instance. + * + * @return ApiResponse _default + **/ + @Deprecated + public ApiResponse getDefault() { + return this.get(DEFAULT); + } + + @Deprecated + public void setDefault(ApiResponse _default) { + addApiResponse(DEFAULT, _default); + } + + @Deprecated + public ApiResponses _default(ApiResponse _default) { + setDefault(_default); + return this; + } + + public java.util.Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(java.util.Map extensions) { + this.extensions = extensions; + } + + public ApiResponses extensions(java.util.Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + ApiResponses apiResponses = (ApiResponses) o; + return Objects.equals(this.extensions, apiResponses.extensions); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), extensions); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ApiResponses {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append(" extensions: ").append(toIndentedString(extensions)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/Server.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/Server.java new file mode 100644 index 00000000000..8a9115f7a44 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/Server.java @@ -0,0 +1,162 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.servers; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; + +import java.util.Objects; + +/** + * Server + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#serverObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#serverObject" + */ +public class Server { + private String url = null; + private String description = null; + private ServerVariables variables = null; + private java.util.Map extensions = null; + + /** + * returns the url property from a Server instance. + * + * @return String url + **/ + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public Server url(String url) { + this.url = url; + return this; + } + + /** + * returns the description property from a Server instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Server description(String description) { + this.description = description; + return this; + } + + /** + * returns the variables property from a Server instance. + * + * @return ServerVariables variables + **/ + public ServerVariables getVariables() { + return variables; + } + + public void setVariables(ServerVariables variables) { + this.variables = variables; + } + + public Server variables(ServerVariables variables) { + this.variables = variables; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Server server = (Server) o; + return Objects.equals(this.url, server.url) + && Objects.equals(this.description, server.description) + && Objects.equals(this.variables, server.variables) + && Objects.equals(this.extensions, server.extensions); + } + + @Override + public int hashCode() { + return Objects.hash(url, description, variables, extensions); + } + + public java.util.Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new java.util.LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(java.util.Map extensions) { + this.extensions = extensions; + } + + public Server extensions(java.util.Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Server {\n"); + + sb.append(" url: ").append(toIndentedString(url)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" variables: ").append(toIndentedString(variables)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/ServerVariable.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/ServerVariable.java new file mode 100644 index 00000000000..205150e8280 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/ServerVariable.java @@ -0,0 +1,172 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.servers; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * ServerVariable + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#serverVariableObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#serverVariableObject" + */ +public class ServerVariable { + private List _enum = null; + private String _default = null; + private String description = null; + private java.util.Map extensions = null; + + /** + * returns the _enum property from a ServerVariable instance. + * + * @return List<String> _enum + **/ + public List getEnum() { + return _enum; + } + + public void setEnum(List _enum) { + this._enum = _enum; + } + + public ServerVariable _enum(List _enum) { + this._enum = _enum; + return this; + } + + public ServerVariable addEnumItem(String _enumItem) { + if (this._enum == null) { + this._enum = new ArrayList<>(); + } + this._enum.add(_enumItem); + return this; + } + + /** + * returns the _default property from a ServerVariable instance. + * + * @return String _default + **/ + public String getDefault() { + return _default; + } + + public void setDefault(String _default) { + this._default = _default; + } + + public ServerVariable _default(String _default) { + this._default = _default; + return this; + } + + /** + * returns the description property from a ServerVariable instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public ServerVariable description(String description) { + this.description = description; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ServerVariable serverVariable = (ServerVariable) o; + return Objects.equals(this._enum, serverVariable._enum) + && Objects.equals(this._default, serverVariable._default) + && Objects.equals(this.description, serverVariable.description) + && Objects.equals(this.extensions, serverVariable.extensions); + } + + @Override + public int hashCode() { + return Objects.hash(_enum, _default, description, extensions); + } + + public java.util.Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new java.util.LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(java.util.Map extensions) { + this.extensions = extensions; + } + + public ServerVariable extensions(java.util.Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ServerVariable {\n"); + + sb.append(" _enum: ").append(toIndentedString(_enum)).append("\n"); + sb.append(" _default: ").append(toIndentedString(_default)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/ServerVariables.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/ServerVariables.java new file mode 100644 index 00000000000..b439edc0c5b --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/servers/ServerVariables.java @@ -0,0 +1,112 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.servers; + +import java.util.LinkedHashMap; +import java.util.Objects; + +/** + * ServerVariables + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#serverVariablesObject" + */ +public class ServerVariables extends LinkedHashMap { + public ServerVariables() {} + + private java.util.Map extensions = null; + + public ServerVariables addServerVariable(String name, ServerVariable item) { + this.put(name, item); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ServerVariables serverVariables = (ServerVariables) o; + return Objects.equals(this.extensions, serverVariables.extensions) && super.equals(o); + } + + @Override + public int hashCode() { + return Objects.hash(extensions, super.hashCode()); + } + + /** + * @deprecated As extensions don't make sense at this level + */ + @Deprecated + public java.util.Map getExtensions() { + return extensions; + } + + /** + * @deprecated As extensions don't make sense at this level + */ + @Deprecated + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + /** + * @deprecated As extensions don't make sense at this level + */ + @Deprecated + public void setExtensions(java.util.Map extensions) { + this.extensions = extensions; + } + + /** + * @deprecated As extensions don't make sense at this level + */ + @Deprecated + public ServerVariables extensions(java.util.Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ServerVariables {\n"); + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/tags/Tag.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/tags/Tag.java new file mode 100644 index 00000000000..6e56ff6f653 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/model/tags/Tag.java @@ -0,0 +1,141 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.model.tags; + +import org.apache.dubbo.metadata.swagger.model.annotations.OpenAPI31; + +import java.util.Objects; + +/** + * Tag + * + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#tagObject" + * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.0/versions/3.1.0.md#tagObject" + */ +public class Tag { + private String name = null; + private String description = null; + private java.util.Map extensions = null; + + /** + * returns the name property from a Tag instance. + * + * @return String name + **/ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Tag name(String name) { + this.name = name; + return this; + } + + /** + * returns the description property from a Tag instance. + * + * @return String description + **/ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Tag description(String description) { + this.description = description; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tag tag = (Tag) o; + return Objects.equals(this.name, tag.name) + && Objects.equals(this.description, tag.description) + && Objects.equals(this.extensions, tag.extensions); + } + + @Override + public int hashCode() { + return Objects.hash(name, description, extensions); + } + + public java.util.Map getExtensions() { + return extensions; + } + + public void addExtension(String name, Object value) { + if (name == null || name.isEmpty() || !name.startsWith("x-")) { + return; + } + if (this.extensions == null) { + this.extensions = new java.util.LinkedHashMap<>(); + } + this.extensions.put(name, value); + } + + @OpenAPI31 + public void addExtension31(String name, Object value) { + if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { + return; + } + addExtension(name, value); + } + + public void setExtensions(java.util.Map extensions) { + this.extensions = extensions; + } + + public Tag extensions(java.util.Map extensions) { + this.extensions = extensions; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Tag {\n"); + + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PathUtils.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PathUtils.java new file mode 100644 index 00000000000..b5b07c9f832 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PathUtils.java @@ -0,0 +1,127 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.utils; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.StringUtils; + +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PathUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(PathUtils.class); + private static final char COLON = ':'; + private static final char OPEN = '{'; + private static final char CLOSE = '}'; + private static final char SLASH = '/'; + private static final Pattern TRIM_PATTERN = Pattern.compile("^/*(.*?)/*$"); + + public static String parsePath(String uri, Map patterns) { + if (uri == null) { + return null; + } else if (StringUtils.isBlank(uri)) { + return String.valueOf(SLASH); + } + CharacterIterator ci = new StringCharacterIterator(uri); + StringBuilder pathBuffer = new StringBuilder(); + char c = ci.first(); + if (c == CharacterIterator.DONE) { + return String.valueOf(SLASH); + } + do { + if (c == OPEN) { + String regexBuffer = cutParameter(ci, patterns); + if (regexBuffer == null) { + LOGGER.warn("Operation path \"{}\" contains syntax error.", uri); + return null; + } + pathBuffer.append(regexBuffer); + } else { + int length = pathBuffer.length(); + if (!(c == SLASH && (length != 0 && pathBuffer.charAt(length - 1) == SLASH))) { + pathBuffer.append(c); + } + } + } while ((c = ci.next()) != CharacterIterator.DONE); + return pathBuffer.toString(); + } + + public static String collectPath(String... pathParts) { + final StringBuilder sb = new StringBuilder(); + for (String item : pathParts) { + if (StringUtils.isBlank(item)) { + continue; + } + final String path = trimPath(item); + if (StringUtils.isNotBlank(path)) { + sb.append(SLASH).append(path); + } + } + return sb.length() > 0 ? sb.toString() : String.valueOf(SLASH); + } + + private static String trimPath(String value) { + final Matcher matcher = TRIM_PATTERN.matcher(value); + return matcher.find() && StringUtils.isNotBlank(matcher.group(1)) ? matcher.group(1) : null; + } + + private static String cutParameter(CharacterIterator ci, Map patterns) { + StringBuilder regexBuffer = new StringBuilder(); + int braceCount = 1; + for (char regexChar = ci.next(); regexChar != CharacterIterator.DONE; regexChar = ci.next()) { + if (regexChar == OPEN) { + braceCount++; + } else if (regexChar == CLOSE) { + braceCount--; + if (braceCount == 0) { + break; + } + } + regexBuffer.append(regexChar); + } + if (braceCount != 0) { + return null; + } + String regex = StringUtils.trimToNull(regexBuffer.toString()); + if (regex == null) { + return null; + } + StringBuilder pathBuffer = new StringBuilder(); + pathBuffer.append(OPEN); + int index = regex.indexOf(COLON); + if (index != -1) { + final String name = StringUtils.trimToNull(regex.substring(0, index)); + final String value = StringUtils.trimToNull(regex.substring(index + 1, regex.length())); + if (name != null) { + pathBuffer.append(name); + if (value != null) { + patterns.put(name, value); + } + } else { + return null; + } + } else { + pathBuffer.append(regex); + } + pathBuffer.append(CLOSE); + return pathBuffer.toString(); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PrimitiveType.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PrimitiveType.java new file mode 100644 index 00000000000..973117c1489 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PrimitiveType.java @@ -0,0 +1,458 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.utils; + +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.metadata.swagger.model.media.BinarySchema; +import org.apache.dubbo.metadata.swagger.model.media.BooleanSchema; +import org.apache.dubbo.metadata.swagger.model.media.ByteArraySchema; +import org.apache.dubbo.metadata.swagger.model.media.DateSchema; +import org.apache.dubbo.metadata.swagger.model.media.DateTimeSchema; +import org.apache.dubbo.metadata.swagger.model.media.FileSchema; +import org.apache.dubbo.metadata.swagger.model.media.IntegerSchema; +import org.apache.dubbo.metadata.swagger.model.media.NumberSchema; +import org.apache.dubbo.metadata.swagger.model.media.Schema; +import org.apache.dubbo.metadata.swagger.model.media.StringSchema; +import org.apache.dubbo.metadata.swagger.model.media.UUIDSchema; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; + +/** + * The PrimitiveType enumeration defines a mapping of limited set + * of classes into Swagger primitive types. + */ +public enum PrimitiveType { + STRING(String.class, "string") { + @Override + public Schema createProperty() { + return new StringSchema(); + } + }, + BOOLEAN(Boolean.class, "boolean") { + @Override + public Schema createProperty() { + return new BooleanSchema(); + } + }, + BYTE(Byte.class, "byte") { + @Override + public Schema createProperty() { + if ((System.getProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY) != null + && System.getProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY) + .equals( + Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_STRING_SCHEMA + .toString())) + || (System.getenv(Schema.BINARY_STRING_CONVERSION_PROPERTY) != null + && System.getenv(Schema.BINARY_STRING_CONVERSION_PROPERTY) + .equals( + Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_STRING_SCHEMA + .toString()))) { + return new StringSchema().format("byte"); + } + return new ByteArraySchema(); + } + }, + BINARY(Byte.class, "binary") { + @Override + public Schema createProperty() { + if ((System.getProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY) != null + && System.getProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY) + .equals( + Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_STRING_SCHEMA + .toString())) + || (System.getenv(Schema.BINARY_STRING_CONVERSION_PROPERTY) != null + && System.getenv(Schema.BINARY_STRING_CONVERSION_PROPERTY) + .equals( + Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_STRING_SCHEMA + .toString()))) { + return new StringSchema().format("binary"); + } + return new BinarySchema(); + } + }, + URI(java.net.URI.class, "uri") { + @Override + public Schema createProperty() { + return new StringSchema().format("uri"); + } + }, + URL(java.net.URL.class, "url") { + @Override + public Schema createProperty() { + return new StringSchema().format("url"); + } + }, + EMAIL(String.class, "email") { + @Override + public Schema createProperty() { + return new StringSchema().format("email"); + } + }, + UUID(java.util.UUID.class, "uuid") { + @Override + public UUIDSchema createProperty() { + return new UUIDSchema(); + } + }, + INT(Integer.class, "integer") { + @Override + public IntegerSchema createProperty() { + return new IntegerSchema(); + } + }, + LONG(Long.class, "long") { + @Override + public Schema createProperty() { + return new IntegerSchema().format("int64"); + } + }, + FLOAT(Float.class, "float") { + @Override + public Schema createProperty() { + return new NumberSchema().format("float"); + } + }, + DOUBLE(Double.class, "double") { + @Override + public Schema createProperty() { + return new NumberSchema().format("double"); + } + }, + INTEGER(java.math.BigInteger.class) { + @Override + public Schema createProperty() { + return new IntegerSchema().format(null); + } + }, + DECIMAL(java.math.BigDecimal.class, "number") { + @Override + public Schema createProperty() { + return new NumberSchema(); + } + }, + NUMBER(Number.class, "number") { + @Override + public Schema createProperty() { + return new NumberSchema(); + } + }, + DATE(DateStub.class, "date") { + @Override + public DateSchema createProperty() { + return new DateSchema(); + } + }, + DATE_TIME(java.util.Date.class, "date-time") { + @Override + public DateTimeSchema createProperty() { + return new DateTimeSchema(); + } + }, + PARTIAL_TIME(java.time.LocalTime.class, "partial-time") { + @Override + public Schema createProperty() { + return new StringSchema().format("partial-time"); + } + }, + FILE(java.io.File.class, "file") { + @Override + public FileSchema createProperty() { + return new FileSchema(); + } + }, + OBJECT(Object.class) { + @Override + public Schema createProperty() { + return new Schema().type("object"); + } + }; + + private static final Map, PrimitiveType> KEY_CLASSES; + private static final Map, Collection> MULTI_KEY_CLASSES; + private static final Map, PrimitiveType> BASE_CLASSES; + /** + * Adds support of a small number of "well-known" types, specifically for + * Joda lib. + */ + private static final Map EXTERNAL_CLASSES; + + /** + * Allows to exclude specific classes from KEY_CLASSES mappings to primitive + * + */ + private static Set customExcludedClasses = ConcurrentHashMap.newKeySet(); + + /** + * Allows to exclude specific classes from EXTERNAL_CLASSES mappings to primitive + * + */ + private static Set customExcludedExternalClasses = ConcurrentHashMap.newKeySet(); + + /** + * Adds support for custom mapping of classes to primitive types + */ + private static Map customClasses = new ConcurrentHashMap<>(); + + /** + * class qualified names prefixes to be considered as "system" types + */ + private static Set systemPrefixes = ConcurrentHashMap.newKeySet(); + /** + * class qualified names NOT to be considered as "system" types + */ + private static Set nonSystemTypes = ConcurrentHashMap.newKeySet(); + /** + * package names NOT to be considered as "system" types + */ + private static Set nonSystemTypePackages = ConcurrentHashMap.newKeySet(); + + /** + * Alternative names for primitive types that have to be supported for + * backward compatibility. + */ + private static final Map NAMES; + + private final Class keyClass; + private final String commonName; + + public static final Map datatypeMappings; + + static { + systemPrefixes.add("java."); + systemPrefixes.add("javax."); + nonSystemTypes.add("java.time.LocalTime"); + + final Map dms = new HashMap<>(); + dms.put("integer_int32", "integer"); + dms.put("integer_", "integer"); + dms.put("integer_int64", "long"); + dms.put("number_", "number"); + dms.put("number_float", "float"); + dms.put("number_double", "double"); + dms.put("string_", "string"); + dms.put("string_byte", "byte"); + dms.put("string_email", "email"); + dms.put("string_binary", "binary"); + dms.put("string_uri", "uri"); + dms.put("string_url", "url"); + dms.put("string_uuid", "uuid"); + dms.put("string_date", "date"); + dms.put("string_date-time", "date-time"); + dms.put("string_partial-time", "partial-time"); + dms.put("string_password", "password"); + dms.put("boolean_", "boolean"); + dms.put("object_", "object"); + datatypeMappings = Collections.unmodifiableMap(dms); + + final Map, PrimitiveType> keyClasses = new HashMap<>(); + addKeys(keyClasses, BOOLEAN, Boolean.class, Boolean.TYPE); + addKeys(keyClasses, STRING, String.class, Character.class, Character.TYPE); + addKeys(keyClasses, BYTE, Byte.class, Byte.TYPE); + addKeys(keyClasses, URL, java.net.URL.class); + addKeys(keyClasses, URI, java.net.URI.class); + addKeys(keyClasses, UUID, java.util.UUID.class); + addKeys(keyClasses, INT, Integer.class, Integer.TYPE, Short.class, Short.TYPE); + addKeys(keyClasses, LONG, Long.class, Long.TYPE); + addKeys(keyClasses, FLOAT, Float.class, Float.TYPE); + addKeys(keyClasses, DOUBLE, Double.class, Double.TYPE); + addKeys(keyClasses, INTEGER, java.math.BigInteger.class); + addKeys(keyClasses, DECIMAL, java.math.BigDecimal.class); + addKeys(keyClasses, NUMBER, Number.class); + addKeys(keyClasses, DATE, DateStub.class); + addKeys(keyClasses, DATE_TIME, java.util.Date.class); + addKeys(keyClasses, FILE, java.io.File.class); + addKeys(keyClasses, OBJECT, Object.class); + KEY_CLASSES = Collections.unmodifiableMap(keyClasses); + + final Map, Collection> multiKeyClasses = new HashMap<>(); + addMultiKeys(multiKeyClasses, BYTE, byte[].class); + addMultiKeys(multiKeyClasses, BINARY, byte[].class); + MULTI_KEY_CLASSES = Collections.unmodifiableMap(multiKeyClasses); + + final Map, PrimitiveType> baseClasses = new HashMap<>(); + addKeys(baseClasses, DATE_TIME, java.util.Date.class, java.util.Calendar.class); + BASE_CLASSES = Collections.unmodifiableMap(baseClasses); + + final Map externalClasses = new HashMap<>(); + addKeys(externalClasses, DATE, "org.joda.time.LocalDate", "java.time.LocalDate"); + addKeys( + externalClasses, + DATE_TIME, + "java.time.LocalDateTime", + "java.time.ZonedDateTime", + "java.time.OffsetDateTime", + "javax.xml.datatype.XMLGregorianCalendar", + "org.joda.time.LocalDateTime", + "org.joda.time.ReadableDateTime", + "org.joda.time.DateTime", + "java.time.Instant"); + EXTERNAL_CLASSES = Collections.unmodifiableMap(externalClasses); + + final Map names = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + for (PrimitiveType item : values()) { + final String name = item.getCommonName(); + if (name != null) { + addKeys(names, item, name); + } + } + addKeys(names, INT, "int"); + addKeys(names, OBJECT, "object"); + NAMES = Collections.unmodifiableMap(names); + } + + private PrimitiveType(Class keyClass) { + this(keyClass, null); + } + + private PrimitiveType(Class keyClass, String commonName) { + this.keyClass = keyClass; + this.commonName = commonName; + } + + /** + * Adds support for custom mapping of classes to primitive types + * + * @return Map of custom classes to primitive type + * @since 2.0.6 + */ + public static Set customExcludedClasses() { + return customExcludedClasses; + } + + /** + * Adds support for custom mapping of classes to primitive types + * + * @return Map of custom classes to primitive type + * @since 2.1.2 + */ + public static Set customExcludedExternalClasses() { + return customExcludedExternalClasses; + } + + /** + * Adds support for custom mapping of classes to primitive types + * + * @return Map of custom classes to primitive type + * @since 2.0.6 + */ + public static Map customClasses() { + return customClasses; + } + + /** + * class qualified names prefixes to be considered as "system" types + * + * @return Mutable set of class qualified names prefixes to be considered as "system" types + * @since 2.0.6 + */ + public static Set systemPrefixes() { + return systemPrefixes; + } + + /** + * class qualified names NOT to be considered as "system" types + * + * @return Mutable set of class qualified names NOT to be considered as "system" types + * @since 2.0.6 + */ + public static Set nonSystemTypes() { + return nonSystemTypes; + } + + /** + * package names NOT to be considered as "system" types + * + * @return Mutable set of package names NOT to be considered as "system" types + * @since 2.0.6 + */ + public static Set nonSystemTypePackages() { + return nonSystemTypePackages; + } + + public static PrimitiveType fromName(String name) { + if (name == null) { + return null; + } + PrimitiveType fromName = NAMES.get(name); + if (fromName == null) { + if (!customExcludedExternalClasses().contains(name)) { + fromName = EXTERNAL_CLASSES.get(name); + } + } + return fromName; + } + + public static PrimitiveType fromTypeAndFormat(String type, String format) { + if (StringUtils.isNotBlank(type) && type.equals("object")) { + return null; + } + return fromName(datatypeMappings.get(String.format( + "%s_%s", StringUtils.isBlank(type) ? "" : type, StringUtils.isBlank(format) ? "" : format))); + } + + public static Schema createProperty(String name) { + final PrimitiveType item = fromName(name); + return item == null ? null : item.createProperty(); + } + + public Class getKeyClass() { + return keyClass; + } + + public String getCommonName() { + return commonName; + } + + public abstract Schema createProperty(); + + private static void addKeys(Map map, PrimitiveType type, K... keys) { + for (K key : keys) { + map.put(key, type); + } + } + + private static void addMultiKeys(Map> map, PrimitiveType type, K... keys) { + for (K key : keys) { + if (!map.containsKey(key)) { + map.put(key, new ArrayList<>()); + } + map.get(key).add(type); + } + } + + private static class DateStub { + private DateStub() {} + } + + /** + * Convenience method to map LocalTime to string primitive with rfc3339 format partial-time. + * See https://xml2rfc.tools.ietf.org/public/rfc/html/rfc3339.html#anchor14 + * + * @since 2.0.6 + */ + public static void enablePartialTime() { + customClasses().put("org.joda.time.LocalTime", PrimitiveType.PARTIAL_TIME); + customClasses().put("java.time.LocalTime", PrimitiveType.PARTIAL_TIME); + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/ReturnTypeParser.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/ReturnTypeParser.java new file mode 100644 index 00000000000..2375485b120 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/ReturnTypeParser.java @@ -0,0 +1,25 @@ +/* + * 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 org.apache.dubbo.metadata.swagger.utils; + +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.MethodMeta; + +import java.lang.reflect.Type; + +public interface ReturnTypeParser { + Type getReturnType(MethodMeta methodMeta); +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceDelegation.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceDelegation.java index 55041f96e88..6428cc9f783 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceDelegation.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceDelegation.java @@ -24,15 +24,25 @@ import org.apache.dubbo.metadata.InstanceMetadataChangedListener; import org.apache.dubbo.metadata.MetadataInfo; import org.apache.dubbo.metadata.MetadataService; +import org.apache.dubbo.metadata.swagger.OpenAPIGenerator; +import org.apache.dubbo.metadata.swagger.OpenAPIService; +import org.apache.dubbo.metadata.swagger.ParameterService; +import org.apache.dubbo.metadata.swagger.RequestBodyService; +import org.apache.dubbo.metadata.swagger.RequestService; +import org.apache.dubbo.metadata.swagger.ResponseService; +import org.apache.dubbo.metadata.swagger.model.OpenAPI; +import org.apache.dubbo.metadata.swagger.model.OperationService; import org.apache.dubbo.registry.client.ServiceDiscovery; import org.apache.dubbo.registry.support.RegistryManager; import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.DefaultRequestMappingRegistry; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.SortedSet; @@ -55,6 +65,7 @@ public class MetadataServiceDelegation implements MetadataService, Disposable { private final ApplicationModel applicationModel; private final RegistryManager registryManager; + private final OpenAPIGenerator openAPIGenerator; private ConcurrentMap instanceMetadataChangedListenerMap = new ConcurrentHashMap<>(); private URL url; @@ -66,6 +77,20 @@ public class MetadataServiceDelegation implements MetadataService, Disposable { public MetadataServiceDelegation(ApplicationModel applicationModel) { this.applicationModel = applicationModel; registryManager = RegistryManager.getInstance(applicationModel); + DefaultRequestMappingRegistry defaultRequestMappingRegistry = + applicationModel.getBeanFactory().getBean(DefaultRequestMappingRegistry.class); + ResponseService responseService = applicationModel.getBeanFactory().getOrRegisterBean(ResponseService.class); + + OpenAPI openAPI = new OpenAPI(); + OpenAPIService openAPIService = new OpenAPIService(openAPI); + + ParameterService parameterService = applicationModel.getBeanFactory().getOrRegisterBean(ParameterService.class); + OperationService operationService = applicationModel.getBeanFactory().getOrRegisterBean(OperationService.class); + RequestBodyService requestBodyService = new RequestBodyService(parameterService); + + RequestService requestService = new RequestService(parameterService,requestBodyService,operationService); + openAPIGenerator = + new OpenAPIGenerator(defaultRequestMappingRegistry, requestService, openAPIService, responseService); } /** @@ -214,6 +239,11 @@ public String getAndListenInstanceMetadata(String consumerId, InstanceMetadataCh return instanceMetadata; } + @Override + public OpenAPI getOpenAPI() { + return openAPIGenerator.getOpenApi(Locale.US); + } + private SortedSet getServiceURLs( Map> exportedServiceURLs, String serviceKey, String protocol) { diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java index 8ec6bf4716c..f3ea3bb4eb2 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java @@ -46,6 +46,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -66,6 +67,7 @@ public final class DefaultRequestMappingRegistry implements RequestMappingRegist private RestConfig restConfig; private List resolvers; private RadixTree tree; + private final Map handlerMetaMap = new HashMap<>(); public DefaultRequestMappingRegistry(FrameworkModel frameworkModel) { this.frameworkModel = frameworkModel; @@ -169,6 +171,7 @@ private void register0(RequestMapping mapping, HandlerMeta handler, AtomicIntege } else if (LOGGER.isWarnEnabled()) { LOGGER.internalWarn(Messages.DUPLICATE_MAPPING.format(path, mapping, handler.getMethod(), exists)); } + handlerMetaMap.put(mapping, handler); } } finally { lock.writeLock().unlock(); @@ -188,6 +191,10 @@ public void unregister(Invoker invoker) { } } + public Map getRegistrations() { + return handlerMetaMap; + } + @Override public void destroy() { if (tree == null) { diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java index 4264594e012..c7520da076a 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java @@ -220,6 +220,18 @@ public ProducesCondition getProducesCondition() { return producesCondition; } + public ConsumesCondition getConsumesCondition() { + return consumesCondition; + } + + public HeadersCondition getHeadersCondition() { + return headersCondition; + } + + public ParamsCondition getParamsCondition() { + return paramsCondition; + } + public CorsMeta getCors() { return cors; } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/ConsumesCondition.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/ConsumesCondition.java index 181d4c4a1c6..8791a77caff 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/ConsumesCondition.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/ConsumesCondition.java @@ -18,6 +18,7 @@ import org.apache.dubbo.remoting.http12.HttpHeaderNames; import org.apache.dubbo.remoting.http12.HttpRequest; +import org.apache.dubbo.remoting.http12.message.MediaType; import java.util.ArrayList; import java.util.Collections; @@ -76,6 +77,17 @@ private ConsumesCondition(List expressions) { this.expressions = expressions; } + public List getMediaTypes() { + List expressions = this.expressions; + int size = expressions.size(); + List mediaTypes = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + MediaTypeExpression expr = expressions.get(i); + mediaTypes.add(new MediaType(expr.getType(), expr.getSubType())); + } + return mediaTypes; + } + @Override public ConsumesCondition combine(ConsumesCondition other) { return other.expressions.isEmpty() ? this : other; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/HeadersCondition.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/HeadersCondition.java index 2a69d3b1b4b..55b0781d347 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/HeadersCondition.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/HeadersCondition.java @@ -46,6 +46,10 @@ public HeadersCondition(String... headers) { this.expressions = expressions == null ? Collections.emptySet() : expressions; } + public Set getExpressions() { + return Collections.unmodifiableSet(expressions); + } + private HeadersCondition(Set expressions) { this.expressions = expressions; } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/ParamsCondition.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/ParamsCondition.java index 63e792d63da..92474b122a1 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/ParamsCondition.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/ParamsCondition.java @@ -18,6 +18,7 @@ import org.apache.dubbo.remoting.http12.HttpRequest; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; @@ -33,6 +34,10 @@ private ParamsCondition(Set expressions) { this.expressions = expressions; } + public Set getExpressions() { + return Collections.unmodifiableSet(expressions); + } + @Override public ParamsCondition combine(ParamsCondition other) { Set set = new LinkedHashSet<>(expressions); From 0d78db4e32a88d512a60f3d20579744d0a48ee23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E4=BA=AE?= Date: Sun, 20 Oct 2024 23:40:03 +0800 Subject: [PATCH 2/3] code format --- .../registry/client/metadata/MetadataServiceDelegation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceDelegation.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceDelegation.java index 6428cc9f783..54aa0324cdf 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceDelegation.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceDelegation.java @@ -88,7 +88,7 @@ public MetadataServiceDelegation(ApplicationModel applicationModel) { OperationService operationService = applicationModel.getBeanFactory().getOrRegisterBean(OperationService.class); RequestBodyService requestBodyService = new RequestBodyService(parameterService); - RequestService requestService = new RequestService(parameterService,requestBodyService,operationService); + RequestService requestService = new RequestService(parameterService, requestBodyService, operationService); openAPIGenerator = new OpenAPIGenerator(defaultRequestMappingRegistry, requestService, openAPIService, responseService); } From 5914d9e1064b630d74581fa4357ce828651d66a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E4=BA=AE?= Date: Sun, 20 Oct 2024 23:56:25 +0800 Subject: [PATCH 3/3] change log format --- .../java/org/apache/dubbo/metadata/swagger/OpenAPIService.java | 1 - .../java/org/apache/dubbo/metadata/swagger/utils/PathUtils.java | 1 - 2 files changed, 2 deletions(-) diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIService.java index 88ec41ca5e9..a889fc9c470 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/OpenAPIService.java @@ -92,7 +92,6 @@ public OpenAPI build() { String jsonString = jackson.toJson(openAPI); calculatedOpenAPI = jackson.toJavaObject(jsonString, OpenAPI.class); } catch (JsonParseException e) { - LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage()); calculatedOpenAPI = openAPI; } } diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PathUtils.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PathUtils.java index b5b07c9f832..8845fbbf85c 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PathUtils.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/swagger/utils/PathUtils.java @@ -50,7 +50,6 @@ public static String parsePath(String uri, Map patterns) { if (c == OPEN) { String regexBuffer = cutParameter(ci, patterns); if (regexBuffer == null) { - LOGGER.warn("Operation path \"{}\" contains syntax error.", uri); return null; } pathBuffer.append(regexBuffer);