add oas-generator to generate openapi v3
Signed-off-by: kakulisen <18813972746@163.com>
diff --git a/oas-generator/oas-generator-core/pom.xml b/oas-generator/oas-generator-core/pom.xml
new file mode 100644
index 0000000..1a7a35c
--- /dev/null
+++ b/oas-generator/oas-generator-core/pom.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>oas-generator</artifactId>
+ <groupId>org.apache.servicecomb.toolkit</groupId>
+ <version>0.2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>oas-generator-core</artifactId>
+
+ <properties>
+ <swagger.version>2.0.9</swagger.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-models</artifactId>
+ <version>${swagger.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-annotations</artifactId>
+ <version>${swagger.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-core</artifactId>
+ <version>${swagger.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm</artifactId>
+ <version>7.2</version>
+ </dependency>
+
+ </dependencies>
+
+
+</project>
\ No newline at end of file
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/HttpStatus.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/HttpStatus.java
new file mode 100644
index 0000000..00a12e3
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/HttpStatus.java
@@ -0,0 +1,24 @@
+/*
+ * 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.servicecomb.toolkit.generator;
+
+public class HttpStatus {
+
+ public static String OK = "200";
+
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/MediaTypeConst.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/MediaTypeConst.java
new file mode 100644
index 0000000..624e143
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/MediaTypeConst.java
@@ -0,0 +1,54 @@
+/*
+ * 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.servicecomb.toolkit.generator;
+
+/**
+ * Common media type constants
+ *
+ * @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7">HTTP/1.1 section 3.7</a>
+ */
+public class MediaTypeConst {
+
+ public final static String WILDCARD = "*/*";
+
+ public final static String APPLICATION_XML = "application/xml";
+
+ public final static String APPLICATION_ATOM_XML = "application/atom+xml";
+
+ public final static String APPLICATION_XHTML_XML = "application/xhtml+xml";
+
+ public final static String APPLICATION_SVG_XML = "application/svg+xml";
+
+ public final static String APPLICATION_JSON = "application/json";
+
+ public final static String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded";
+
+ public final static String MULTIPART_FORM_DATA = "multipart/form-data";
+
+ public final static String APPLICATION_OCTET_STREAM = "application/octet-stream";
+
+ public final static String TEXT_PLAIN = "text/plain";
+
+ public final static String TEXT_XML = "text/xml";
+
+ public final static String TEXT_HTML = "text/html";
+
+ public final static String SERVER_SENT_EVENTS = "text/event-stream";
+
+ public final static String APPLICATION_JSON_PATCH_JSON = "application/json-patch+json";
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/OasContext.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/OasContext.java
new file mode 100644
index 0000000..3be7edb
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/OasContext.java
@@ -0,0 +1,151 @@
+/*
+ * 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.servicecomb.toolkit.generator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.toolkit.generator.parser.api.OpenApiAnnotationParser;
+
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.PathItem;
+import io.swagger.v3.oas.models.PathItem.HttpMethod;
+import io.swagger.v3.oas.models.Paths;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.servers.Server;
+
+public class OasContext {
+
+ private OpenAPI openAPI;
+
+ private String basePath;
+
+ private Class<?> cls;
+
+ private List<OperationContext> operationList = new ArrayList<>();
+
+ private OpenApiAnnotationParser parser;
+
+ public OasContext(OpenApiAnnotationParser parser) {
+ this(new OpenAPI(), parser);
+ }
+
+ public OasContext(OpenAPI openAPI, OpenApiAnnotationParser parser) {
+ this.openAPI = openAPI;
+ this.parser = parser;
+ }
+
+ public OpenAPI toOpenAPI() {
+ ensurePaths();
+ for (OperationContext operationCtx : operationList) {
+ if (!operationCtx.hasOperation()) {
+ continue;
+ }
+
+ if (openAPI.getPaths() == null) {
+ openAPI.setPaths(new Paths());
+ }
+
+ PathItem pathItem = openAPI.getPaths().get(operationCtx.getPath());
+ if (pathItem == null) {
+ pathItem = new PathItem();
+ openAPI.path(operationCtx.getPath(), pathItem);
+ }
+ pathItem.operation(HttpMethod.valueOf(operationCtx.getHttpMethod()), operationCtx.toOperation());
+ }
+
+ // 如果没有restful资源则返回null
+ if (openAPI.getPaths() == null || openAPI.getPaths().size() == 0) {
+ return null;
+ }
+
+ openAPI.info(new Info().title("gen").version("1.0.0"));
+
+ correctBasepath();
+ correctComponents();
+
+ openAPI.servers(Collections.singletonList(new Server().url(basePath)));
+
+ return openAPI;
+ }
+
+ private void correctComponents() {
+ Components nullComponents = new Components();
+ if (nullComponents.equals(getComponents())) {
+ openAPI.setComponents(null);
+ }
+ }
+
+ private void correctBasepath() {
+ if (StringUtils.isEmpty(basePath)) {
+ basePath = "/";
+ }
+
+ if (!basePath.startsWith("/")) {
+ basePath = "/" + basePath;
+ }
+ }
+
+ public Components getComponents() {
+ if (openAPI.getComponents() == null) {
+ openAPI.setComponents(new Components());
+ }
+ return openAPI.getComponents();
+ }
+
+ private void ensurePaths() {
+ if (openAPI.getPaths() == null) {
+ openAPI.setPaths(new Paths());
+ }
+ }
+
+ public OpenApiAnnotationParser getParser() {
+ return parser;
+ }
+
+ public void setParser(OpenApiAnnotationParser parser) {
+ this.parser = parser;
+ }
+
+ public OpenAPI getOpenAPI() {
+ return openAPI;
+ }
+
+ public String getBasePath() {
+ return basePath;
+ }
+
+ public Class<?> getCls() {
+ return cls;
+ }
+
+ public void setCls(Class<?> cls) {
+ this.cls = cls;
+ }
+
+ public void setBasePath(String basePath) {
+ this.basePath = basePath;
+ }
+
+ public void addOperation(OperationContext operation) {
+ operationList.add(operation);
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/OasGenerator.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/OasGenerator.java
new file mode 100644
index 0000000..540f320
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/OasGenerator.java
@@ -0,0 +1,63 @@
+/*
+ * 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.servicecomb.toolkit.generator;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.apache.servicecomb.toolkit.generator.parser.api.OpenApiAnnotationParser;
+
+import io.swagger.v3.oas.models.OpenAPI;
+
+public class OasGenerator {
+
+ private static List<OpenApiAnnotationParser> parserList = new ArrayList<>();
+
+ static {
+ ServiceLoader.load(OpenApiAnnotationParser.class).forEach(parserList::add);
+ }
+
+ public OpenAPI generate(Class<?> cls) {
+
+ Optional<OpenApiAnnotationParser> parserOptional = parserList.stream().filter(parser -> parser.canProcess(cls))
+ .findFirst();
+
+ if (!parserOptional.isPresent()) {
+ return null;
+ }
+ OasContext context = new OasContext(parserOptional.get());
+ parserOptional.get().parser(cls, context);
+ return context.toOpenAPI();
+ }
+
+ public List<OpenAPI> generate(Set<Class> classes) {
+
+ List<OpenAPI> openApiList = new ArrayList<>();
+ for (Class cls : classes) {
+ OpenAPI openAPI = generate(cls);
+ if (openAPI != null) {
+ openApiList.add(openAPI);
+ }
+ }
+
+ return openApiList;
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/OperationContext.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/OperationContext.java
new file mode 100644
index 0000000..b8bca12
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/OperationContext.java
@@ -0,0 +1,192 @@
+/*
+ * 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.servicecomb.toolkit.generator;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.toolkit.generator.parser.api.OpenApiAnnotationParser;
+import org.apache.servicecomb.toolkit.generator.util.ModelConverter;
+
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.media.Content;
+import io.swagger.v3.oas.models.media.MediaType;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.parameters.Parameter;
+import io.swagger.v3.oas.models.responses.ApiResponse;
+import io.swagger.v3.oas.models.responses.ApiResponses;
+
+public class OperationContext {
+
+ private OasContext parentContext;
+
+ private Method method;
+
+ private Operation operation = new Operation();
+
+ private String operationId;
+
+ private String path;
+
+ private String httpMethod;
+
+ private ApiResponses apiResponses = new ApiResponses();
+
+ private List<ParameterContext> parameterContextList = new ArrayList<>();
+
+ private OpenApiAnnotationParser parser;
+
+ public OperationContext(Method method, OasContext parentContext) {
+ this.parentContext = parentContext;
+ this.method = method;
+ this.parser = parentContext.getParser();
+ this.parentContext.addOperation(this);
+ }
+
+ public void addParameter(ParameterContext context) {
+ parameterContextList.add(context);
+ }
+
+ public OpenApiAnnotationParser getParser() {
+ return parser;
+ }
+
+ public boolean hasOperation() {
+ return httpMethod != null && method != null;
+ }
+
+ public Operation toOperation() {
+
+ if (!hasOperation()) {
+ return null;
+ }
+
+ if (StringUtils.isEmpty(operationId)) {
+ operationId = method.getName();
+ }
+
+ operation.operationId(operationId);
+ correctResponse(apiResponses);
+ operation.setResponses(apiResponses);
+
+ // 处理参数
+ List<Parameter> parameterList = parameterContextList.stream()
+ .map(parameterContext -> parameterContext.toOasParameter())
+ .filter(parameter -> parameter != null)
+ .collect(Collectors.toList());
+
+ if (parameterList.size() > 0) {
+ operation.parameters(parameterList);
+ }
+
+ return operation;
+ }
+
+ public void correctResponse(ApiResponses apiResponses) {
+
+ if (apiResponses == null) {
+ return;
+ }
+ // 处理响应
+ // 没有注解被处理
+ if (apiResponses.get(HttpStatus.OK) == null) {
+ ApiResponse apiResponse = new ApiResponse();
+
+ Class<?> returnType = method.getReturnType();
+ if (returnType == Void.TYPE || returnType == Void.class) {
+ return;
+ }
+
+ MediaType mediaType = new MediaType();
+
+ Schema refSchema = ModelConverter.getSchema(returnType, getComponents());
+ mediaType.schema(refSchema);
+
+ Content content = new Content();
+ content.addMediaType(MediaTypeConst.TEXT_PLAIN, mediaType);
+
+ apiResponse.description("OK");
+ apiResponse.setContent(content);
+ apiResponses.addApiResponse(HttpStatus.OK, apiResponse);
+ }
+ }
+
+ public Components getComponents() {
+ return parentContext.getComponents();
+ }
+
+ public void addResponse(String key, ApiResponse response) {
+ apiResponses.addApiResponse(key, response);
+ }
+
+ public ApiResponses getApiResponses() {
+ return apiResponses;
+ }
+
+ public void setApiResponses(ApiResponses apiResponses) {
+ this.apiResponses = apiResponses;
+ }
+
+ public String getOperationId() {
+ return operationId;
+ }
+
+ public void setOperationId(String operationId) {
+ this.operationId = operationId;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public Operation getOperation() {
+ return operation;
+ }
+
+ public OpenAPI getOpenAPI() {
+ return parentContext.getOpenAPI();
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ public OasContext getOpenApiContext() {
+ return parentContext;
+ }
+
+ public String getHttpMethod() {
+ return httpMethod;
+ }
+
+ public void setHttpMethod(String httpMethod) {
+ if (this.httpMethod != null) {
+ throw new IllegalArgumentException(String.format("too many http method in the method %s", method.getName()));
+ }
+ this.httpMethod = httpMethod.toUpperCase();
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/ParameterContext.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/ParameterContext.java
new file mode 100644
index 0000000..15e6721
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/ParameterContext.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.servicecomb.toolkit.generator;
+
+import java.lang.reflect.Parameter;
+import java.lang.reflect.Type;
+
+import org.apache.servicecomb.toolkit.generator.util.ModelConverter;
+import org.apache.servicecomb.toolkit.generator.util.ParamUtils;
+
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.media.Schema;
+
+public class ParameterContext {
+
+ private OperationContext parentContext;
+
+ private boolean required;
+
+ private String name;
+
+ Parameter parameter;
+
+ private Object defaultValue;
+
+
+ io.swagger.v3.oas.models.parameters.Parameter oasParameter = new io.swagger.v3.oas.models.parameters.Parameter();
+
+ public ParameterContext(OperationContext parentContext, Parameter parameter) {
+ this.parentContext = parentContext;
+ this.parameter = parameter;
+ this.parentContext.addParameter(this);
+ }
+
+
+ public io.swagger.v3.oas.models.parameters.Parameter toOasParameter() {
+
+ if (parameter == null) {
+ return null;
+ }
+ ensureName();
+ if (oasParameter.getSchema() == null) {
+ Schema refSchema = ModelConverter.getSchema(parameter.getType(), getComponents());
+ oasParameter.schema(refSchema);
+ }
+
+ if (oasParameter.getIn() == null) {
+ oasParameter.setIn(ParameterIn.QUERY.toString());
+ }
+
+ if (defaultValue != null) {
+ required = false;
+ oasParameter.getSchema().setDefault(defaultValue);
+ }
+
+ oasParameter.setRequired(required);
+
+ return oasParameter;
+ }
+
+ private void ensureName() {
+ if (name == null) {
+ // 尝试获取实际参数名
+ name = ParamUtils.getParamterName(parentContext.getMethod(), parameter);
+ }
+
+ if (name == null) {
+ name = parameter.getName();
+ }
+
+ oasParameter.setName(name);
+ }
+
+ public OperationContext getOperationContext() {
+ return parentContext;
+ }
+
+ public Type getActualType() {
+ return parameter.getParameterizedType();
+ }
+
+ public Object getDefaultValue() {
+ return defaultValue;
+ }
+
+ public void setDefaultValue(Object defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+ public Components getComponents() {
+ return parentContext.getComponents();
+ }
+
+ public io.swagger.v3.oas.models.parameters.Parameter getOasParameter() {
+ return oasParameter;
+ }
+
+ public Parameter getParameter() {
+ return parameter;
+ }
+
+ public void setParameter(Parameter parameter) {
+ this.parameter = parameter;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ public void setRequired(boolean required) {
+ this.required = required;
+ }
+
+ public void setType(String type) {
+ oasParameter.setIn(type);
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/AnnotationProcessor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/AnnotationProcessor.java
new file mode 100644
index 0000000..5827b55
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/AnnotationProcessor.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.servicecomb.toolkit.generator.annotation;
+
+public interface AnnotationProcessor<Annotation, Context> {
+ void process(Annotation annotation, Context context);
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ApiResponseMethodAnnotationProcessor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ApiResponseMethodAnnotationProcessor.java
new file mode 100644
index 0000000..3cbbe0a
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ApiResponseMethodAnnotationProcessor.java
@@ -0,0 +1,63 @@
+/*
+ * 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.servicecomb.toolkit.generator.annotation;
+
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.toolkit.generator.OperationContext;
+
+import io.swagger.v3.oas.annotations.headers.Header;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.models.media.MediaType;
+
+public class ApiResponseMethodAnnotationProcessor implements
+ MethodAnnotationProcessor<ApiResponse, OperationContext> {
+ @Override
+ public void process(ApiResponse response, OperationContext context) {
+
+ io.swagger.v3.oas.models.responses.ApiResponse apiResponse = new io.swagger.v3.oas.models.responses.ApiResponse();
+
+ Content[] contentAnnotations = response.content();
+ Optional.ofNullable(contentAnnotations).ifPresent(contents -> {
+ for (Content contentAnnotation : contents) {
+ io.swagger.v3.oas.models.media.Content content = new io.swagger.v3.oas.models.media.Content();
+ MediaType mediaType = new MediaType();
+ content.addMediaType(contentAnnotation.mediaType(), mediaType);
+ apiResponse.setContent(content);
+ }
+ });
+
+ if (StringUtils.isNotEmpty(response.description())) {
+ apiResponse.setDescription(response.description());
+ }
+
+ Header[] headersAnnotation = response.headers();
+ Optional.ofNullable(headersAnnotation).ifPresent(headers -> {
+ for (Header headerAnnotation : headers) {
+ io.swagger.v3.oas.models.headers.Header header = new io.swagger.v3.oas.models.headers.Header();
+ header.description(headerAnnotation.description());
+ header.deprecated(headerAnnotation.deprecated());
+ apiResponse.addHeaderObject(headerAnnotation.name(), header);
+ }
+ });
+
+ context.addResponse(response.responseCode(), apiResponse);
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ApiResponsesMethodAnnotationProcessor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ApiResponsesMethodAnnotationProcessor.java
new file mode 100644
index 0000000..54747ae
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ApiResponsesMethodAnnotationProcessor.java
@@ -0,0 +1,39 @@
+/*
+ * 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.servicecomb.toolkit.generator.annotation;
+
+import java.util.Arrays;
+
+import org.apache.servicecomb.toolkit.generator.OperationContext;
+
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+
+public class ApiResponsesMethodAnnotationProcessor implements
+ MethodAnnotationProcessor<ApiResponses, OperationContext> {
+ @Override
+ public void process(ApiResponses responses, OperationContext context) {
+
+ MethodAnnotationProcessor apiResponseAnnotationProcessor = context.getParser()
+ .findMethodAnnotationProcessor(ApiResponse.class);
+
+ if (apiResponseAnnotationProcessor != null) {
+ Arrays.stream(responses.value()).forEach(response -> apiResponseAnnotationProcessor.process(response, context));
+ }
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ClassAnnotationProcessor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ClassAnnotationProcessor.java
new file mode 100644
index 0000000..55d11be
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ClassAnnotationProcessor.java
@@ -0,0 +1,21 @@
+/*
+ * 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.servicecomb.toolkit.generator.annotation;
+
+public interface ClassAnnotationProcessor<Annotation, Context> extends AnnotationProcessor<Annotation, Context> {
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/MethodAnnotationProcessor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/MethodAnnotationProcessor.java
new file mode 100644
index 0000000..cff77a6
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/MethodAnnotationProcessor.java
@@ -0,0 +1,21 @@
+/*
+ * 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.servicecomb.toolkit.generator.annotation;
+
+public interface MethodAnnotationProcessor<Annotation, Context> extends AnnotationProcessor<Annotation, Context> {
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ModelInterceptor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ModelInterceptor.java
new file mode 100644
index 0000000..8415e1a
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ModelInterceptor.java
@@ -0,0 +1,28 @@
+/*
+ * 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.servicecomb.toolkit.generator.annotation;
+
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.media.Schema;
+
+public interface ModelInterceptor {
+
+ int order();
+
+ Schema process(Class<?> cls, Components components);
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/OperationMethodAnnotationProcessor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/OperationMethodAnnotationProcessor.java
new file mode 100644
index 0000000..517ea5b
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/OperationMethodAnnotationProcessor.java
@@ -0,0 +1,57 @@
+/*
+ * 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.servicecomb.toolkit.generator.annotation;
+
+import org.apache.servicecomb.toolkit.generator.OperationContext;
+
+import io.swagger.v3.oas.annotations.ExternalDocumentation;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.extensions.Extension;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.servers.Server;
+
+public class OperationMethodAnnotationProcessor implements MethodAnnotationProcessor<Operation, OperationContext> {
+
+ @Override
+ public void process(Operation annotation, OperationContext context) {
+
+ context.setOperationId(annotation.operationId());
+ String s = annotation.operationId();
+ boolean deprecated = annotation.deprecated();
+ String description = annotation.description();
+ Extension[] extensions = annotation.extensions();
+ ExternalDocumentation externalDocumentation = annotation.externalDocs();
+ RequestBody requestBody = annotation.requestBody();
+ ApiResponse[] responses = annotation.responses();
+ String method = annotation.method();
+ Server[] servers = annotation.servers();
+ SecurityRequirement[] security = annotation.security();
+ String[] tags = annotation.tags();
+ String summary = annotation.summary();
+ Parameter[] parameters = annotation.parameters();
+
+// context.getOpenAPI().setPaths();
+
+ // responseReference未解析
+ // hidden未解析
+ // authorizations未解析
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ParamAnnotationProcessor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ParamAnnotationProcessor.java
new file mode 100644
index 0000000..5b2b393
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ParamAnnotationProcessor.java
@@ -0,0 +1,21 @@
+/*
+ * 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.servicecomb.toolkit.generator.annotation;
+
+public interface ParamAnnotationProcessor<Annotation, ParameterContext> extends AnnotationProcessor<Annotation, ParameterContext> {
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ParameterAnnotationProcessor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ParameterAnnotationProcessor.java
new file mode 100644
index 0000000..139bb0b
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/annotation/ParameterAnnotationProcessor.java
@@ -0,0 +1,53 @@
+/*
+ * 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.servicecomb.toolkit.generator.annotation;
+
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.toolkit.generator.ParameterContext;
+
+import io.swagger.v3.core.util.ParameterProcessor;
+import io.swagger.v3.core.util.ReflectionUtils;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+public class ParameterAnnotationProcessor implements ParamAnnotationProcessor<Parameter, ParameterContext> {
+
+ @Override
+ public void process(Parameter parameter, ParameterContext parameterContext) {
+
+ Schema schema = parameter.schema();
+ Type type = parameterContext.getActualType();
+ if (schema != null) {
+
+ if (StringUtils.isNotEmpty(schema.type())) {
+ parameterContext.setType(schema.type());
+ type = ReflectionUtils.typeFromString(schema.type());
+ }
+ }
+
+ ParameterProcessor
+ .applyAnnotations(parameterContext.getOasParameter(), type, Arrays.asList(parameter),
+ parameterContext.getComponents(),
+ null, null, null);
+
+ parameterContext.setRequired(parameter.required());
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/parser/AbstractAnnotationParser.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/parser/AbstractAnnotationParser.java
new file mode 100644
index 0000000..5b3a4fa
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/parser/AbstractAnnotationParser.java
@@ -0,0 +1,152 @@
+/*
+ * 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.servicecomb.toolkit.generator.parser;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.servicecomb.toolkit.generator.OasContext;
+import org.apache.servicecomb.toolkit.generator.OperationContext;
+import org.apache.servicecomb.toolkit.generator.ParameterContext;
+import org.apache.servicecomb.toolkit.generator.annotation.AnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.ApiResponseMethodAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.ApiResponsesMethodAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.ClassAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.MethodAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.OperationMethodAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.ParamAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.ParameterAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.parser.api.OpenApiAnnotationParser;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+
+public abstract class AbstractAnnotationParser implements OpenApiAnnotationParser {
+
+ private Class<?> cls;
+
+ private OasContext context;
+
+ protected Map<Class, ClassAnnotationProcessor> classAnnotationMap = new HashMap<>();
+
+ protected Map<Class, MethodAnnotationProcessor> methodAnnotationMap = new HashMap<>();
+
+ protected Map<Class, ParamAnnotationProcessor> parameterAnnotationMap = new HashMap<>();
+
+ public AbstractAnnotationParser() {
+ initMethodAnnotationProcessor();
+ initClassAnnotationProcessor();
+ initParameterAnnotationProcessor();
+ }
+
+ @Override
+ public void parser(Class<?> cls, OasContext context) {
+
+ this.cls = cls;
+ this.context = context;
+
+ if (!canProcess(cls)) {
+ return;
+ }
+
+ for (Annotation clsAnnotation : cls.getAnnotations()) {
+ AnnotationProcessor annotationProcessor = classAnnotationMap.get(clsAnnotation.annotationType());
+ if (annotationProcessor == null) {
+ continue;
+ }
+ annotationProcessor.process(clsAnnotation, context);
+ }
+ postParseClassAnnotaion(context);
+
+ List<Method> methods = Arrays.asList(cls.getDeclaredMethods());
+ methods.sort(Comparator.comparing(Method::getName));
+ for (Method m : methods) {
+ OperationContext operationContext = new OperationContext(m, context);
+ for (Annotation methodAnnotation : m.getAnnotations()) {
+ MethodAnnotationProcessor annotationProcessor = methodAnnotationMap.get(methodAnnotation.annotationType());
+ if (annotationProcessor != null) {
+ annotationProcessor.process(methodAnnotation, operationContext);
+ }
+ }
+
+ postParseMethodAnnotation(operationContext);
+
+ java.lang.reflect.Parameter[] parameters = m.getParameters();
+
+ for (java.lang.reflect.Parameter parameter : parameters) {
+ ParameterContext parameterContext = new ParameterContext(operationContext, parameter);
+ for (Annotation paramAnnotation : parameter.getAnnotations()) {
+ ParamAnnotationProcessor paramAnnotationProcessor = parameterAnnotationMap
+ .get(paramAnnotation.annotationType());
+ if (paramAnnotationProcessor != null) {
+ paramAnnotationProcessor.process(paramAnnotation, parameterContext);
+ }
+ }
+ postParseParameterAnnotation(parameterContext);
+ }
+ }
+ }
+
+ @Override
+ public void postParseClassAnnotaion(OasContext context) {
+ }
+
+ @Override
+ public void postParseMethodAnnotation(OperationContext context) {
+ }
+
+ @Override
+ public void postParseParameterAnnotation(ParameterContext context) {
+ }
+
+ public void initMethodAnnotationProcessor() {
+ methodAnnotationMap.put(Operation.class, new OperationMethodAnnotationProcessor());
+ methodAnnotationMap.put(ApiResponse.class, new ApiResponseMethodAnnotationProcessor());
+ methodAnnotationMap.put(ApiResponses.class, new ApiResponsesMethodAnnotationProcessor());
+ }
+
+ public void initClassAnnotationProcessor() {
+
+ }
+
+ public void initParameterAnnotationProcessor() {
+ parameterAnnotationMap.put(Parameter.class, new ParameterAnnotationProcessor());
+ }
+
+ @Override
+ public ClassAnnotationProcessor findClassAnnotationProcessor(Class<? extends Annotation> annotationType) {
+ return classAnnotationMap.get(annotationType);
+ }
+
+ @Override
+ public MethodAnnotationProcessor findMethodAnnotationProcessor(Class<? extends Annotation> annotationType) {
+ return methodAnnotationMap.get(annotationType);
+ }
+
+ @Override
+ public ParamAnnotationProcessor findParameterAnnotationProcessor(Class<? extends Annotation> annotationType) {
+ return parameterAnnotationMap.get(annotationType);
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/parser/api/OpenApiAnnotationParser.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/parser/api/OpenApiAnnotationParser.java
new file mode 100644
index 0000000..1fbdd9e
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/parser/api/OpenApiAnnotationParser.java
@@ -0,0 +1,57 @@
+/*
+ * 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.servicecomb.toolkit.generator.parser.api;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.servicecomb.toolkit.generator.OasContext;
+import org.apache.servicecomb.toolkit.generator.OperationContext;
+import org.apache.servicecomb.toolkit.generator.ParameterContext;
+import org.apache.servicecomb.toolkit.generator.annotation.ClassAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.MethodAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.ParamAnnotationProcessor;
+
+public interface OpenApiAnnotationParser {
+
+ /**
+ *
+ * @param cls
+ * @param context
+ */
+ void parser(Class<?> cls, OasContext context);
+
+ /**
+ * 用于排序, 对于同一个类,同时只能为springmvc或者jaxrs其中一种
+ * @return
+ */
+ int getOrder();
+
+ boolean canProcess(Class<?> cls);
+
+ void postParseClassAnnotaion(OasContext context);
+
+ void postParseMethodAnnotation(OperationContext context);
+
+ void postParseParameterAnnotation(ParameterContext context);
+
+ ClassAnnotationProcessor findClassAnnotationProcessor(Class<? extends Annotation> annotationType);
+
+ MethodAnnotationProcessor findMethodAnnotationProcessor(Class<? extends Annotation> annotationType);
+
+ ParamAnnotationProcessor findParameterAnnotationProcessor(Class<? extends Annotation> annotationType);
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/ArrayModelConverter.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/ArrayModelConverter.java
new file mode 100644
index 0000000..f52c57d
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/ArrayModelConverter.java
@@ -0,0 +1,55 @@
+/*
+ * 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.servicecomb.toolkit.generator.util;
+
+import java.util.Iterator;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+import io.swagger.v3.core.converter.AnnotatedType;
+import io.swagger.v3.core.converter.ModelConverter;
+import io.swagger.v3.core.converter.ModelConverterContext;
+import io.swagger.v3.core.jackson.AbstractModelConverter;
+import io.swagger.v3.oas.models.media.ArraySchema;
+import io.swagger.v3.oas.models.media.Schema;
+
+public class ArrayModelConverter extends AbstractModelConverter {
+
+ protected ArrayModelConverter(ObjectMapper mapper) {
+ super(mapper);
+ }
+
+ @Override
+ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator<ModelConverter> chain) {
+
+ String typeName = _typeName(TypeFactory.defaultInstance().constructType(type.getType()));
+
+ ArraySchema schema;
+ if ("Array".equals(typeName)) {
+ schema = new ArraySchema();
+ if (!(type.getType() instanceof Class)) {
+ return null;
+ }
+ Schema itemSchema = context.resolve(new AnnotatedType(((Class) type.getType()).getComponentType()));
+ schema.setItems(itemSchema);
+ return schema;
+ }
+ return super.resolve(type, context, chain);
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/LocalVariableVisitor.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/LocalVariableVisitor.java
new file mode 100644
index 0000000..b7f19c1
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/LocalVariableVisitor.java
@@ -0,0 +1,71 @@
+/*
+ * 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.servicecomb.toolkit.generator.util;
+
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+
+public class LocalVariableVisitor extends MethodVisitor {
+
+ private boolean isStatic;
+
+ private String[] parameterNames;
+
+ private final int[] lvtSlotIndex;
+
+ private final Type[] args;
+
+ public LocalVariableVisitor(int api, String desc, boolean isStatic, String[] parameterNames) {
+ super(api);
+ this.isStatic = isStatic;
+ this.parameterNames = parameterNames;
+ this.args = Type.getArgumentTypes(desc);
+ this.lvtSlotIndex = computeLvtSlotIndices(isStatic, this.args);
+ }
+
+ @Override
+ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end,
+ int index) {
+
+ for (int i = 0; i < this.lvtSlotIndex.length; i++) {
+ if (this.lvtSlotIndex[i] == index) {
+ this.parameterNames[i] = name;
+ }
+ }
+ super.visitLocalVariable(name, descriptor, signature, start, end, index);
+ }
+
+ int[] computeLvtSlotIndices(boolean isStatic, Type[] paramTypes) {
+ int[] lvtIndex = new int[paramTypes.length];
+ int nextIndex = (isStatic ? 0 : 1);
+ for (int i = 0; i < paramTypes.length; i++) {
+ lvtIndex[i] = nextIndex;
+ if (isWideType(paramTypes[i])) {
+ nextIndex += 2;
+ } else {
+ nextIndex++;
+ }
+ }
+ return lvtIndex;
+ }
+
+ private boolean isWideType(Type aType) {
+ return (aType == Type.LONG_TYPE || aType == Type.DOUBLE_TYPE);
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/ModelConverter.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/ModelConverter.java
new file mode 100644
index 0000000..0370c31
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/ModelConverter.java
@@ -0,0 +1,142 @@
+/*
+ * 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.servicecomb.toolkit.generator.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import org.apache.servicecomb.toolkit.generator.annotation.ModelInterceptor;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.swagger.v3.core.converter.AnnotatedType;
+import io.swagger.v3.core.converter.ModelConverterContextImpl;
+import io.swagger.v3.core.jackson.ModelResolver;
+import io.swagger.v3.core.util.PrimitiveType;
+import io.swagger.v3.core.util.RefUtils;
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.media.ArraySchema;
+import io.swagger.v3.oas.models.media.Schema;
+
+public class ModelConverter {
+
+ private static final ModelConverterContextImpl context;
+
+ private static final List<ModelInterceptor> interceptorMgr = new ArrayList<>();
+
+ static {
+
+ ServiceLoader.load(ModelInterceptor.class).forEach(ModelConverter::registerInterceptor);
+
+ ArrayModelConverter arrayModelConverter = new ArrayModelConverter(mapper());
+ ModelResolver modelResolver = new ModelResolver(mapper());
+
+ context = new ModelConverterContextImpl(Arrays.asList(arrayModelConverter, modelResolver));
+ }
+
+ public static void registerInterceptor(ModelInterceptor interceptor) {
+ interceptorMgr.add(interceptor);
+ interceptorMgr.sort(Comparator.comparingInt(ModelInterceptor::order));
+ }
+
+ public static Schema getSchema(Class<?> cls) {
+ return getSchema(cls, null);
+ }
+
+ public static Schema getSchema(Class<?> cls, Components components) {
+
+ for (ModelInterceptor interceptor : interceptorMgr) {
+ Schema schema = interceptor.process(cls, components);
+ if (schema != null) {
+ return schema;
+ }
+ }
+
+ Schema schema = PrimitiveType.createProperty(cls);
+ if (schema == null) {
+ schema = context
+ .resolve(new AnnotatedType(cls));
+ }
+
+ if (components == null) {
+ return schema;
+ }
+
+ Schema refSchema = schema;
+
+ if (shouldExtractRef(schema)) {
+ ensureSchemaNameExist(schema);
+ schema.$ref(null);
+ components.addSchemas(schema.getName(), schema);
+ refSchema = new Schema();
+ refSchema.set$ref(RefUtils.constructRef(schema.getName()));
+ }
+
+ if (schema instanceof ArraySchema) {
+ ArraySchema arraySchema = (ArraySchema) schema;
+ Schema itemSchema = arraySchema.getItems();
+ if (shouldExtractRef(itemSchema)) {
+ ensureSchemaNameExist(itemSchema);
+ itemSchema.$ref(null);
+ components.addSchemas(itemSchema.getName(), itemSchema);
+
+ Schema itemRefSchema = new Schema();
+ itemRefSchema.set$ref(RefUtils.constructRef(itemSchema.getName()));
+ arraySchema.setItems(itemRefSchema);
+ }
+
+ refSchema = arraySchema;
+ }
+
+ return refSchema;
+ }
+
+ private static void ensureSchemaNameExist(Schema schema) {
+ if (schema.getName() != null) {
+ return;
+ }
+
+ if (schema.get$ref() != null) {
+ schema.setName((String) RefUtils.extractSimpleName(schema.get$ref()).getKey());
+ return;
+ }
+ }
+
+ public static boolean shouldExtractRef(Schema schema) {
+ if (schema.getName() != null || schema.get$ref() != null) {
+ return true;
+ }
+ return false;
+ }
+
+
+ public static ObjectMapper mapper() {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ return mapper;
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/ParamUtils.java b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/ParamUtils.java
new file mode 100644
index 0000000..9093630
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/main/java/org/apache/servicecomb/toolkit/generator/util/ParamUtils.java
@@ -0,0 +1,122 @@
+/*
+ * 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.servicecomb.toolkit.generator.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Parameter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+public class ParamUtils {
+
+ private static final String STATIC_CLASS_INIT = "<clinit>";
+
+ public static final Map<Method, String[]> paramterCache = new HashMap();
+
+ public static String getParamterName(Method method, Parameter parameter) {
+
+ String[] parameterNames = paramterCache.get(method);
+
+ if (parameterNames == null) {
+ parameterNames = initParamterNames(method);
+ if (parameterNames == null) {
+ return null;
+ }
+ }
+
+ int paramIndex = getParamIndex(method, parameter);
+ if (paramIndex >= 0) {
+ return parameterNames[paramIndex];
+ }
+
+ return null;
+ }
+
+ private static int getParamIndex(Method method, Parameter parameter) {
+ Parameter[] parameters = method.getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ if (parameters[i].equals(parameter)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private static String[] initParamterNames(Method m) {
+
+ boolean isStatic = Modifier.isStatic(m.getModifiers());
+ String[] paramterNames = new String[m.getParameterCount()];
+
+ try {
+
+ String className = m.getDeclaringClass().getName();
+ String classRawName = className.replace('.', '/') + ".class";
+
+ InputStream is = null;
+ ClassLoader classLoader = m.getDeclaringClass().getClassLoader();
+ if (classLoader != null) {
+ is = classLoader.getResourceAsStream(classRawName);
+ } else {
+ is = m.getDeclaringClass().getResourceAsStream(classRawName);
+ }
+
+ if (is == null) {
+ return null;
+ }
+ ClassReader clsReader = new ClassReader(is);
+ ClassWriter clsWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+
+ clsReader.accept(new ClassVisitor(Opcodes.ASM7, clsWriter) {
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
+ String[] exceptions) {
+ MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);
+ if (!m.getName().equals(name) || !descriptor.equals(Type.getMethodDescriptor(m))) {
+ return methodVisitor;
+ }
+
+ if (!isSyntheticOrBridged(access) && !STATIC_CLASS_INIT.equals(name)) {
+ return new LocalVariableVisitor(this.api, descriptor, isStatic, paramterNames);
+ }
+
+ return methodVisitor;
+ }
+ }, 0);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ paramterCache.put(m, paramterNames);
+
+ return paramterNames;
+ }
+
+ private static boolean isSyntheticOrBridged(int access) {
+ return (((access & Opcodes.ACC_SYNTHETIC) | (access & Opcodes.ACC_BRIDGE)) > 0);
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/AnnotationProcessorTest.java b/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/AnnotationProcessorTest.java
new file mode 100644
index 0000000..c6bbf56
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/AnnotationProcessorTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.servicecomb.toolkit.generator;
+
+import java.lang.reflect.Method;
+
+import org.apache.servicecomb.toolkit.generator.annotation.ApiResponseMethodAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.ApiResponsesMethodAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.OperationMethodAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.annotation.ParameterAnnotationProcessor;
+import org.apache.servicecomb.toolkit.generator.parser.AbstractAnnotationParser;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.models.media.StringSchema;
+
+public class AnnotationProcessorTest {
+
+ @Test
+ public void processApiResponseAnnotation() {
+
+ OasContext oasContext = new OasContext(null);
+ OperationContext context = new OperationContext(null, oasContext);
+ ApiResponseMethodAnnotationProcessor apiResProcessor = new ApiResponseMethodAnnotationProcessor();
+ ApiResponse apiResponse = Mockito.mock(ApiResponse.class);
+ Content[] contents = new Content[1];
+ contents[0] = Mockito.mock(Content.class);
+ Mockito.when(contents[0].mediaType()).thenReturn(MediaTypeConst.APPLICATION_JSON);
+ Mockito.when(apiResponse.content()).thenReturn(contents);
+ Mockito.when(apiResponse.responseCode()).thenReturn("200");
+ apiResProcessor.process(apiResponse, context);
+
+ Assert.assertNotNull(context.getApiResponses().get("200"));
+ Assert.assertNull(context.getApiResponses().get("500"));
+ }
+
+ @Test
+ public void processApiResponsesAnnotation() {
+
+ OasContext oasContext = new OasContext(new AbstractAnnotationParser() {
+ @Override
+ public int getOrder() {
+ return 0;
+ }
+
+ @Override
+ public boolean canProcess(Class<?> cls) {
+ return true;
+ }
+ });
+
+ OperationContext context = new OperationContext(null, oasContext);
+ ApiResponsesMethodAnnotationProcessor apiRessProcessor = new ApiResponsesMethodAnnotationProcessor();
+ ApiResponses apiResponses = Mockito.mock(ApiResponses.class);
+ Content[] contents = new Content[1];
+ contents[0] = Mockito.mock(Content.class);
+ Mockito.when(contents[0].mediaType()).thenReturn(MediaTypeConst.APPLICATION_JSON);
+ ApiResponse apiResponse = Mockito.mock(ApiResponse.class);
+ Mockito.when(apiResponse.content()).thenReturn(contents);
+ Mockito.when(apiResponse.responseCode()).thenReturn("200");
+ Mockito.when(apiResponses.value()).thenReturn(new ApiResponse[] {apiResponse});
+
+ apiRessProcessor.process(apiResponses, context);
+
+ Assert.assertNotNull(context.getApiResponses().get("200"));
+ Assert.assertNull(context.getApiResponses().get("500"));
+ }
+
+ @Test
+ public void processOperationAnnotation() {
+
+ OasContext oasContext = new OasContext(null);
+ OperationContext context = new OperationContext(null, oasContext);
+ OperationMethodAnnotationProcessor operationMethodAnnotationProcessor = new OperationMethodAnnotationProcessor();
+ Operation operation = Mockito.mock(Operation.class);
+ operationMethodAnnotationProcessor.process(operation, context);
+ }
+
+
+ @Test
+ public void processParameterAnnotation() throws NoSuchMethodException, IllegalAccessException,
+ InstantiationException {
+
+ OasContext oasContext = new OasContext(null);
+ Method parameterMethod = ParameterClass.class.getMethod("parameter", String.class);
+ OperationContext operationContext = new OperationContext(parameterMethod, oasContext);
+ java.lang.reflect.Parameter[] parameters = parameterMethod.getParameters();
+ Assert.assertEquals(parameters.length, 1);
+ java.lang.reflect.Parameter parameter = parameters[0];
+ Parameter parameterDeclaredAnnotation = parameter.getDeclaredAnnotation(Parameter.class);
+
+ ParameterContext parameterContext = new ParameterContext(operationContext, parameter);
+ ParameterAnnotationProcessor parameterAnnotationProcessor = new ParameterAnnotationProcessor();
+
+ parameterAnnotationProcessor.process(parameterDeclaredAnnotation, parameterContext);
+ io.swagger.v3.oas.models.parameters.Parameter oasParameter = parameterContext.toOasParameter();
+ Assert.assertEquals("param", oasParameter.getName());
+ Assert.assertEquals(StringSchema.class, oasParameter.getSchema().getClass());
+ Assert.assertTrue(parameterContext.isRequired());
+ Assert.assertEquals(operationContext, parameterContext.getOperationContext());
+ Assert.assertNull(parameterContext.getDefaultValue());
+ }
+
+ class ParameterClass {
+ public void parameter(@Parameter(required = true) String param) {
+ }
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/OasGeneratorTest.java b/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/OasGeneratorTest.java
new file mode 100644
index 0000000..d454d7d
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/OasGeneratorTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.servicecomb.toolkit.generator;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.PathItem.HttpMethod;
+
+public class OasGeneratorTest {
+
+ @Test
+ public void generatorOas() {
+
+ Set<Class> classSet = new HashSet<>();
+ classSet.add(NoResource.class);
+ classSet.add(OneResource.class);
+ OasGenerator generator = new OasGenerator();
+ generator.generate(classSet);
+ }
+
+ @Test
+ public void constructOasContext() throws NoSuchMethodException {
+ OasContext oasContext = new OasContext(null);
+
+ Method method = OneResource.class.getMethod("name", String.class);
+ OperationContext operationContext = new OperationContext(method, oasContext);
+ operationContext.setHttpMethod(HttpMethod.GET.name());
+ operationContext.setOperationId(method.getName());
+ operationContext.setPath("/operation");
+
+ oasContext.addOperation(operationContext);
+ oasContext.setCls(method.getDeclaringClass());
+ oasContext.setBasePath("/oas");
+ oasContext.setParser(null);
+
+ Assert.assertEquals("/oas", oasContext.getBasePath());
+ Assert.assertEquals(method.getDeclaringClass(), oasContext.getCls());
+ Assert.assertNull(oasContext.getParser());
+
+ Assert.assertEquals("/operation", operationContext.getPath());
+ Assert.assertEquals(HttpMethod.GET.name(), operationContext.getHttpMethod());
+ Assert.assertEquals(oasContext.getComponents(), operationContext.getComponents());
+ Assert.assertEquals(null, operationContext.getApiResponses().getDefault());
+ Assert.assertEquals(oasContext.getOpenAPI(), operationContext.getOpenAPI());
+
+ Parameter parameter = method.getParameters()[0];
+ ParameterContext parameterContext = new ParameterContext(operationContext, parameter);
+ parameterContext.setName(parameter.getName());
+ parameterContext.setRequired(true);
+ parameterContext.setType(ParameterIn.QUERY.toString());
+
+ Assert.assertEquals(parameter.getName(), parameterContext.getName());
+
+ OpenAPI openAPI = oasContext.toOpenAPI();
+ Assert.assertNotNull(openAPI);
+ }
+
+ class NoResource {
+
+ }
+
+ class OneResource {
+ public String name(String name) {
+ return name;
+ }
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/ParserTest.java b/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/ParserTest.java
new file mode 100644
index 0000000..c0b37e3
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/ParserTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.servicecomb.toolkit.generator;
+
+import org.apache.servicecomb.toolkit.generator.parser.AbstractAnnotationParser;
+import org.junit.Test;
+
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
+public class ParserTest {
+
+ @Test
+ public void parse() {
+ AbstractAnnotationParser parser = new TestParser();
+
+ parser.parser(UnParser.class, new OasContext(parser));
+ }
+
+ class TestParser extends AbstractAnnotationParser {
+
+ @Override
+ public int getOrder() {
+ return 0;
+ }
+
+ @Override
+ public boolean canProcess(Class<?> cls) {
+ return true;
+ }
+ }
+
+ @OpenAPIDefinition
+ class UnParser {
+ @ApiResponse
+ public String name(String name) {
+ return name;
+ }
+ }
+}
diff --git a/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/UtilsTest.java b/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/UtilsTest.java
new file mode 100644
index 0000000..224dbf9
--- /dev/null
+++ b/oas-generator/oas-generator-core/src/test/java/org/apache/servicecomb/toolkit/generator/UtilsTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.servicecomb.toolkit.generator;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+
+import org.apache.servicecomb.toolkit.generator.annotation.ModelInterceptor;
+import org.apache.servicecomb.toolkit.generator.util.ModelConverter;
+import org.apache.servicecomb.toolkit.generator.util.ParamUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.media.ArraySchema;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.media.StringSchema;
+
+public class UtilsTest {
+
+ @Test
+ public void getParameterName() throws NoSuchMethodException {
+
+ Method method = ParameterClass.class.getMethod("method", String.class);
+ Parameter parameter = method.getParameters()[0];
+ String paramterName = ParamUtils.getParamterName(method, parameter);
+ Assert.assertEquals("param", paramterName);
+ }
+
+ @Test
+ public void getSchema() {
+ Schema schema = ModelConverter.getSchema(String.class);
+ Assert.assertEquals(StringSchema.class, schema.getClass());
+
+ schema = ModelConverter.getSchema(ParameterClass.class);
+ Assert.assertEquals(Schema.class, schema.getClass());
+
+ schema = ModelConverter.getSchema(String[].class);
+ Assert.assertEquals(ArraySchema.class, schema.getClass());
+
+ Components components = new Components();
+ schema = ModelConverter.getSchema(ParameterClass[].class, components);
+ Assert.assertEquals(ArraySchema.class, schema.getClass());
+
+ schema = ModelConverter.getSchema(ParameterClass.class, components);
+ Assert.assertNotNull(schema.get$ref());
+
+ ModelConverter.registerInterceptor(new ModelInterceptor() {
+ @Override
+ public int order() {
+ return 0;
+ }
+
+ @Override
+ public Schema process(Class<?> cls, Components components) {
+ return new Schema().name("unknown");
+ }
+ });
+
+ schema = ModelConverter.getSchema(ParameterClass.class);
+ Assert.assertEquals("unknown", schema.getName());
+ }
+
+ class ParameterClass {
+ public void method(String param) {
+ }
+ }
+}
diff --git a/oas-generator/pom.xml b/oas-generator/pom.xml
new file mode 100644
index 0000000..123ec2c
--- /dev/null
+++ b/oas-generator/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>toolkit</artifactId>
+ <groupId>org.apache.servicecomb.toolkit</groupId>
+ <version>0.2.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>pom</packaging>
+ <modules>
+ <module>oas-generator-core</module>
+ </modules>
+
+ <artifactId>oas-generator</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.1</version>
+ <configuration>
+ <target>1.8</target>
+ <source>1.8</source>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file