This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit ed2c00a784e8027a13c568ab8b7e041706f77836 Author: yaohaishi <yaohai...@huawei.com> AuthorDate: Fri Jul 6 18:49:15 2018 +0800 [SCB-708] generate schema for Object query param --- .../swagger/generator/core/OperationGenerator.java | 25 +- .../swagger/generator/core/TestClassUtils.java | 6 +- .../generator/core/TestOperationGenerator.java | 33 ++ .../SpringmvcDefaultObjectParameterProcessor.java | 115 +++++++ .../SpringmvcDefaultParameterProcessor.java | 34 ++- ... SpringmvcDefaultSimpleParameterProcessor.java} | 2 +- ...ringmvcDefaultObjectParameterProcessorTest.java | 337 +++++++++++++++++++++ .../SpringmvcDefaultParameterProcessorTest.java | 162 ++++++++++ ...ringmvcDefaultSimpleParameterProcessorTest.java | 53 ++++ 9 files changed, 754 insertions(+), 13 deletions(-) diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java index 40edc67..ba0b900 100644 --- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java +++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java @@ -32,6 +32,8 @@ import javax.ws.rs.DefaultValue; import org.apache.servicecomb.swagger.SwaggerUtils; import org.apache.servicecomb.swagger.extend.parameter.ContextParameter; import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; import io.swagger.models.HttpMethod; @@ -45,6 +47,8 @@ import io.swagger.models.properties.Property; import io.swagger.util.ReflectionUtils; public class OperationGenerator { + private static final Logger LOGGER = LoggerFactory.getLogger(OperationGenerator.class); + protected SwaggerGenerator swaggerGenerator; protected Swagger swagger; @@ -139,7 +143,27 @@ public class OperationGenerator { methodAnnotationParameters.add(parameter); } + /** + * Add a parameter into {@linkplain #providerParameters}, + * duplicated name params will be ignored(excepting for {@linkplain ContextParameter}s) + */ public void addProviderParameter(Parameter parameter) { + if (ContextParameter.class.isInstance(parameter)) { + // ContextParameter has no name and is not written in schema, + // so just add it without checking + providerParameters.add(parameter); + return; + } + // check duplicated param according to param name + for (Parameter providerParameter : providerParameters) { + if (parameter.getName().equals(providerParameter.getName())) { + LOGGER.warn( + "Param name [{}] is duplicated which may cause ambiguous deserialization result. Please check you schema definition", + parameter.getName()); + return; + } + } + providerParameters.add(parameter); } @@ -294,7 +318,6 @@ public class OperationGenerator { if (parameter instanceof AbstractSerializableParameter && defaultValue != null) { ((AbstractSerializableParameter<?>) parameter).setDefaultValue(defaultValue); } - } protected void processByParameterType(Type parameterType, int paramIdx) { diff --git a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestClassUtils.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestClassUtils.java index 32d8253..d1b2d38 100644 --- a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestClassUtils.java +++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestClassUtils.java @@ -84,10 +84,10 @@ public class TestClassUtils { @Test public void testHasAnnotation() { - Assert.assertEquals(true, ClassUtils.hasAnnotation(TestClassUtils.class, SwaggerDefinition.class)); - Assert.assertEquals(true, ClassUtils.hasAnnotation(TestClassUtils.class, Test.class)); + Assert.assertTrue(ClassUtils.hasAnnotation(TestClassUtils.class, SwaggerDefinition.class)); + Assert.assertTrue(ClassUtils.hasAnnotation(TestClassUtils.class, Test.class)); - Assert.assertEquals(false, ClassUtils.hasAnnotation(TestClassUtils.class, Path.class)); + Assert.assertFalse(ClassUtils.hasAnnotation(TestClassUtils.class, Path.class)); } @Test diff --git a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestOperationGenerator.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestOperationGenerator.java index 1ecb0e6..1b520bc 100644 --- a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestOperationGenerator.java +++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestOperationGenerator.java @@ -26,11 +26,16 @@ import java.util.Collections; import java.util.List; import org.apache.servicecomb.foundation.test.scaffolding.spring.SpringUtils; +import org.apache.servicecomb.swagger.extend.parameter.HttpRequestParameter; import org.apache.servicecomb.swagger.generator.pojo.PojoSwaggerGeneratorContext; +import org.junit.Assert; import org.junit.Test; import org.springframework.util.StringValueResolver; import io.swagger.annotations.ApiOperation; +import io.swagger.models.parameters.BodyParameter; +import io.swagger.models.parameters.Parameter; +import io.swagger.models.parameters.QueryParameter; public class TestOperationGenerator { @Test @@ -88,6 +93,34 @@ public class TestOperationGenerator { assertThat(tagList, contains("default0", "default1")); } + @Test + public void addProviderParameter() throws NoSuchMethodException { + Method function = TestClass.class.getMethod("functionWithNoAnnotation"); + SwaggerGenerator swaggerGenerator = new SwaggerGenerator(new PojoSwaggerGeneratorContext(), TestClass.class); + OperationGenerator operationGenerator = new OperationGenerator(swaggerGenerator, function); + + Parameter parameter = new BodyParameter(); + parameter.setName("param0"); + operationGenerator.addProviderParameter(parameter); + Assert.assertEquals(1, operationGenerator.getProviderParameters().size()); + Assert.assertSame(parameter, operationGenerator.getProviderParameters().get(0)); + + parameter = new HttpRequestParameter(); + operationGenerator.addProviderParameter(parameter); + Assert.assertSame(parameter, operationGenerator.getProviderParameters().get(1)); + + parameter = new QueryParameter(); + parameter.setName("param1"); + operationGenerator.addProviderParameter(parameter); + Assert.assertSame(parameter, operationGenerator.getProviderParameters().get(2)); + + parameter = new QueryParameter(); + parameter.setName("param0"); + operationGenerator.addProviderParameter(parameter); + Assert.assertEquals(3, operationGenerator.getProviderParameters().size()); + Assert.assertNotSame(parameter, operationGenerator.getProviderParameters().get(2)); + } + private static class TestClass { @ApiOperation(value = "value1", tags = {"tag1", "tag2"}) public void function() { diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultObjectParameterProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultObjectParameterProcessor.java new file mode 100644 index 0000000..e5fa320 --- /dev/null +++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultObjectParameterProcessor.java @@ -0,0 +1,115 @@ +/* + * 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.swagger.generator.springmvc.processor.parameter; + +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.servicecomb.swagger.generator.core.DefaultParameterProcessor; +import org.apache.servicecomb.swagger.generator.core.OperationGenerator; +import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.swagger.converter.ModelConverters; +import io.swagger.models.Model; +import io.swagger.models.parameters.AbstractSerializableParameter; +import io.swagger.models.parameters.QueryParameter; +import io.swagger.models.properties.Property; +import io.swagger.models.properties.RefProperty; + +/** + * Flatten a object parameter into a set of flatten simple parameters. + * <p/> + * <em>Nesting object params and generic Object params are NOT supported.</em> + * We support query object just for aggregating query params instead of transporting objects in query param. + * So we don't support a generic param whose generic type is complex, but a simple generic type param can be supported. + */ +public class SpringmvcDefaultObjectParameterProcessor implements DefaultParameterProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(SpringmvcDefaultObjectParameterProcessor.class); + + @Override + public void process(OperationGenerator operationGenerator, int paramIndex) { + Model paramModel = getParamModel(operationGenerator, paramIndex); + + if (null == paramModel) { + LOGGER.warn("cannot find param, provider method is [{}], paramIndex = [{}]", + operationGenerator.getProviderMethod().getName(), paramIndex); + return; + } + + LinkedHashMap<String, AbstractSerializableParameter<?>> resultParamMap = getFlattenParams(paramModel); + + addProviderParams(operationGenerator, resultParamMap); + } + + private void addProviderParams(OperationGenerator operationGenerator, + LinkedHashMap<String, AbstractSerializableParameter<?>> resultParamMap) { + resultParamMap.forEach((paramName, param) -> operationGenerator.addProviderParameter(param)); + } + + private Model getParamModel(OperationGenerator operationGenerator, int paramIndex) { + Type paramType = ParamUtils.getGenericParameterType(operationGenerator.getProviderMethod(), paramIndex); + Property property = ModelConverters.getInstance().readAsProperty(paramType); + // ensure type + if (!RefProperty.class.isInstance(property)) { + LOGGER.error("Unsupported property type: [{}], paramIndex is [{}]", property.getClass().getName(), paramIndex); + return null; + } + + Map<String, Model> models = ModelConverters.getInstance().readAll(paramType); + + // find param root + RefProperty refProperty = (RefProperty) property; + String refTypeName = refProperty.getSimpleRef(); + Model paramRoot = null; + for (Entry<String, Model> entry : models.entrySet()) { + if (refTypeName.equals(entry.getKey())) { + paramRoot = entry.getValue(); + break; + } + } + return paramRoot; + } + + private LinkedHashMap<String, AbstractSerializableParameter<?>> getFlattenParams(Model paramModel) { + LinkedHashMap<String, AbstractSerializableParameter<?>> flattenParamMap = new LinkedHashMap<>(); + // traversal the properties of current paramModel + // create simple parameters, nesting object param is ignored + for (Entry<String, Property> propertyEntry : paramModel.getProperties().entrySet()) { + if (ParamUtils.isComplexProperty(propertyEntry.getValue())) { + LOGGER.info("A nesting complex field is ignored, field name = [{}]", propertyEntry.getKey()); + continue; + } + AbstractSerializableParameter<?> newParameter = createSimpleParam(propertyEntry); + flattenParamMap.put(propertyEntry.getKey(), newParameter); + } + + return flattenParamMap; + } + + private AbstractSerializableParameter<?> createSimpleParam(Entry<String, Property> propertyEntry) { + AbstractSerializableParameter<?> newParameter = new QueryParameter(); + newParameter.setName(propertyEntry.getKey()); + newParameter.setProperty(propertyEntry.getValue()); + return newParameter; + } +} diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessor.java index a87ef87..d9b5a5d 100644 --- a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessor.java +++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessor.java @@ -17,24 +17,42 @@ package org.apache.servicecomb.swagger.generator.springmvc.processor.parameter; +import java.lang.reflect.Type; + import org.apache.servicecomb.swagger.generator.core.DefaultParameterProcessor; import org.apache.servicecomb.swagger.generator.core.OperationGenerator; import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils; -import io.swagger.models.parameters.QueryParameter; +import io.swagger.converter.ModelConverters; +import io.swagger.models.properties.Property; +import io.swagger.models.properties.RefProperty; public class SpringmvcDefaultParameterProcessor implements DefaultParameterProcessor { + private SpringmvcDefaultSimpleParameterProcessor simpleParameterProcessor = new SpringmvcDefaultSimpleParameterProcessor(); + + private SpringmvcDefaultObjectParameterProcessor objectParameterProcessor = new SpringmvcDefaultObjectParameterProcessor(); @Override public void process(OperationGenerator operationGenerator, int paramIdx) { - String paramName = ParamUtils.getParameterName(operationGenerator.getProviderMethod(), paramIdx); + Type paramType = ParamUtils.getGenericParameterType(operationGenerator.getProviderMethod(), paramIdx); + Property property = ModelConverters.getInstance().readAsProperty(paramType); + + if (RefProperty.class.isInstance(property)) { + objectParameterProcessor.process(operationGenerator, paramIdx); + return; + } + if (!ParamUtils.isComplexProperty(property)) { + simpleParameterProcessor.process(operationGenerator, paramIdx); + return; + } - QueryParameter queryParameter = new QueryParameter(); - queryParameter.setName(paramName); - ParamUtils.setParameterType(operationGenerator.getSwagger(), - operationGenerator.getProviderMethod(), + // unsupported param type + String msg = String.format("cannot process parameter [%s], method=%s:%s, paramIdx=%d, type=%s", + ParamUtils.getParameterName(operationGenerator.getProviderMethod(), paramIdx), + operationGenerator.getProviderMethod().getDeclaringClass().getName(), + operationGenerator.getProviderMethod().getName(), paramIdx, - queryParameter); - operationGenerator.addProviderParameter(queryParameter); + paramType.getTypeName()); + throw new Error(msg); } } diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultSimpleParameterProcessor.java similarity index 94% copy from swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessor.java copy to swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultSimpleParameterProcessor.java index a87ef87..3d9f5a1 100644 --- a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessor.java +++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultSimpleParameterProcessor.java @@ -23,7 +23,7 @@ import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils; import io.swagger.models.parameters.QueryParameter; -public class SpringmvcDefaultParameterProcessor implements DefaultParameterProcessor { +public class SpringmvcDefaultSimpleParameterProcessor implements DefaultParameterProcessor { @Override public void process(OperationGenerator operationGenerator, int paramIdx) { diff --git a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultObjectParameterProcessorTest.java b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultObjectParameterProcessorTest.java new file mode 100644 index 0000000..128cbee --- /dev/null +++ b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultObjectParameterProcessorTest.java @@ -0,0 +1,337 @@ +/* + * 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.swagger.generator.springmvc.processor.parameter; + +import java.lang.reflect.Method; +import java.util.List; + +import org.apache.servicecomb.swagger.generator.core.OperationGenerator; +import org.apache.servicecomb.swagger.generator.core.SwaggerGenerator; +import org.apache.servicecomb.swagger.generator.core.SwaggerGeneratorContext; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import io.swagger.models.parameters.Parameter; +import io.swagger.models.parameters.QueryParameter; +import mockit.Deencapsulation; + +public class SpringmvcDefaultObjectParameterProcessorTest { + + @Test + public void processOnObjectParam() throws NoSuchMethodException { + final OperationGenerator operationGenerator = mockOperationGenerator("testObjectParam", "/test", TestParam.class); + + new SpringmvcDefaultObjectParameterProcessor().process(operationGenerator, 0); + + final List<Parameter> providerParameters = operationGenerator.getProviderParameters(); + Assert.assertEquals(2, providerParameters.size()); + Parameter parameter = providerParameters.get(0); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("name", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + QueryParameter queryParameter = (QueryParameter) parameter; + Assert.assertEquals("string", queryParameter.getType()); + parameter = providerParameters.get(1); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("age", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + queryParameter = (QueryParameter) parameter; + Assert.assertEquals("integer", queryParameter.getType()); + Assert.assertEquals("int32", queryParameter.getFormat()); + } + + @Test + public void processOnMultiObjectParamsWithSameFieldName() throws NoSuchMethodException { + final OperationGenerator operationGenerator = mockOperationGenerator("testMultiObjParamsWithSameFiledName", "/test", + String.class, TestParam.class, TestParam.class, int.class); + + final SpringmvcDefaultObjectParameterProcessor springmvcDefaultParameterProcessor = new SpringmvcDefaultObjectParameterProcessor(); + springmvcDefaultParameterProcessor.process(operationGenerator, 0); + springmvcDefaultParameterProcessor.process(operationGenerator, 1); + springmvcDefaultParameterProcessor.process(operationGenerator, 2); + springmvcDefaultParameterProcessor.process(operationGenerator, 3); + + final List<Parameter> providerParameters = operationGenerator.getProviderParameters(); + Assert.assertEquals(2, providerParameters.size()); + Parameter parameter = providerParameters.get(0); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("name", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + QueryParameter queryParameter = (QueryParameter) parameter; + Assert.assertEquals("string", queryParameter.getType()); + parameter = providerParameters.get(1); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("age", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + queryParameter = (QueryParameter) parameter; + Assert.assertEquals("integer", queryParameter.getType()); + Assert.assertEquals("int32", queryParameter.getFormat()); + } + + @Test + public void processOnRecursiveObjectParam() throws NoSuchMethodException { + final OperationGenerator operationGenerator = mockOperationGenerator("testRecursiveParam", "/test", + RecursiveParamA.class); + + new SpringmvcDefaultObjectParameterProcessor().process(operationGenerator, 0); + + final List<Parameter> providerParameters = operationGenerator.getProviderParameters(); + Assert.assertEquals(1, providerParameters.size()); + Parameter parameter = providerParameters.get(0); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("name", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + QueryParameter queryParameter = (QueryParameter) parameter; + Assert.assertEquals("string", queryParameter.getType()); + } + + @Test + public void processOnGenericObjectParam() throws NoSuchMethodException { + final OperationGenerator operationGenerator = mockOperationGenerator("testGenericObjectParam", "/test", + GenericParam.class); + + new SpringmvcDefaultObjectParameterProcessor().process(operationGenerator, 0); + + final List<Parameter> providerParameters = operationGenerator.getProviderParameters(); + Assert.assertEquals(2, providerParameters.size()); + Parameter parameter = providerParameters.get(0); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("num", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + QueryParameter queryParameter = (QueryParameter) parameter; + Assert.assertEquals("integer", queryParameter.getType()); + Assert.assertEquals("int32", queryParameter.getFormat()); + parameter = providerParameters.get(1); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("str", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + queryParameter = (QueryParameter) parameter; + Assert.assertEquals("string", queryParameter.getType()); + } + + @Test + public void processOnGenericSimpleParam() throws NoSuchMethodException { + final OperationGenerator operationGenerator = mockOperationGenerator("testGenericSimpleParam", "/test", + GenericParam.class); + + new SpringmvcDefaultObjectParameterProcessor().process(operationGenerator, 0); + + final List<Parameter> providerParameters = operationGenerator.getProviderParameters(); + Assert.assertEquals(3, providerParameters.size()); + Parameter parameter = providerParameters.get(0); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("num", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + QueryParameter queryParameter = (QueryParameter) parameter; + Assert.assertEquals("integer", queryParameter.getType()); + Assert.assertEquals("int32", queryParameter.getFormat()); + parameter = providerParameters.get(1); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("str", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + queryParameter = (QueryParameter) parameter; + Assert.assertEquals("string", queryParameter.getType()); + parameter = providerParameters.get(2); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("data", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + queryParameter = (QueryParameter) parameter; + Assert.assertEquals("string", queryParameter.getType()); + } + + private OperationGenerator mockOperationGenerator(String providerParamName, String path, Class<?>... classes) + throws NoSuchMethodException { + final SwaggerGenerator swaggerGenerator = new SwaggerGenerator(Mockito.mock(SwaggerGeneratorContext.class), + TestProvider.class); + final Method providerMethod = TestProvider.class + .getDeclaredMethod(providerParamName, classes); + final OperationGenerator operationGenerator = new OperationGenerator(swaggerGenerator, providerMethod); + Deencapsulation.setField(operationGenerator, "path", path); + return operationGenerator; + } + + static class TestProvider { + public String testObjectParam(TestParam objParam) { + return objParam.toString(); + } + + public String testMultiObjParamsWithSameFiledName(String name, TestParam objParam0, TestParam objParam1, int age) { + return objParam0 + "-" + objParam1; + } + + public String testRecursiveParam(RecursiveParamA recursiveParamA) { + return null; + } + + public String testGenericObjectParam(GenericParam<TestParam> genericParam) { + return genericParam.toString(); + } + + public String testGenericSimpleParam(GenericParam<String> genericParam) { + return genericParam.toString(); + } + } + + static class TestParam { + private String name; + + private int age; + + public String getName() { + return name; + } + + public TestParam setName(String name) { + this.name = name; + return this; + } + + public int getAge() { + return age; + } + + public TestParam setAge(int age) { + this.age = age; + return this; + } + } + + static class GenericParam<T> { + private int num; + + private String str; + + T data; + + public int getNum() { + return num; + } + + public void setNum(int num) { + this.num = num; + } + + public String getStr() { + return str; + } + + public void setStr(String str) { + this.str = str; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + } + + static class RecursiveParamA { + private String name; + + private RecursiveParamB recursiveParamB; + + private RecursiveParamC recursiveParamC; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public RecursiveParamB getRecursiveParamB() { + return recursiveParamB; + } + + public void setRecursiveParamB( + RecursiveParamB recursiveParamB) { + this.recursiveParamB = recursiveParamB; + } + + public RecursiveParamC getRecursiveParamC() { + return recursiveParamC; + } + + public void setRecursiveParamC( + RecursiveParamC recursiveParamC) { + this.recursiveParamC = recursiveParamC; + } + } + + static class RecursiveParamB { + private int age; + + private RecursiveParamA recursiveParamA; + + private RecursiveParamC recursiveParamC; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public RecursiveParamA getRecursiveParamA() { + return recursiveParamA; + } + + public void setRecursiveParamA( + RecursiveParamA recursiveParamA) { + this.recursiveParamA = recursiveParamA; + } + + public RecursiveParamC getRecursiveParamC() { + return recursiveParamC; + } + + public void setRecursiveParamC( + RecursiveParamC recursiveParamC) { + this.recursiveParamC = recursiveParamC; + } + } + + static class RecursiveParamC { + private String address; + + private RecursiveParamB recursiveParamB; + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public RecursiveParamB getRecursiveParamB() { + return recursiveParamB; + } + + public void setRecursiveParamB( + RecursiveParamB recursiveParamB) { + this.recursiveParamB = recursiveParamB; + } + } +} \ No newline at end of file diff --git a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessorTest.java b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessorTest.java new file mode 100644 index 0000000..2edafbf --- /dev/null +++ b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultParameterProcessorTest.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.servicecomb.swagger.generator.springmvc.processor.parameter; + +import static org.junit.Assert.fail; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.swagger.generator.core.OperationGenerator; +import org.apache.servicecomb.swagger.generator.core.SwaggerGenerator; +import org.apache.servicecomb.swagger.generator.core.SwaggerGeneratorContext; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import io.swagger.models.parameters.Parameter; +import io.swagger.models.parameters.QueryParameter; +import mockit.Deencapsulation; + +public class SpringmvcDefaultParameterProcessorTest { + @Test + public void processOnSimpleParam() throws NoSuchMethodException { + final SwaggerGenerator swaggerGenerator = new SwaggerGenerator(Mockito.mock(SwaggerGeneratorContext.class), + TestProvider.class); + final Method providerMethod = TestProvider.class.getDeclaredMethod("testSimpleParam", String.class); + final OperationGenerator operationGenerator = new OperationGenerator(swaggerGenerator, providerMethod); + + new SpringmvcDefaultParameterProcessor().process(operationGenerator, 0); + + final List<Parameter> providerParameters = operationGenerator.getProviderParameters(); + Assert.assertEquals(1, providerParameters.size()); + Parameter parameter = providerParameters.get(0); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("strParam", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + QueryParameter queryParameter = (QueryParameter) parameter; + Assert.assertEquals("string", queryParameter.getType()); + } + + @Test + public void processOnObjectParam() throws NoSuchMethodException { + final OperationGenerator operationGenerator = mockOperationGenerator("testObjectParam", "/test", TestParam.class); + + new SpringmvcDefaultParameterProcessor().process(operationGenerator, 0); + + final List<Parameter> providerParameters = operationGenerator.getProviderParameters(); + Assert.assertEquals(2, providerParameters.size()); + Parameter parameter = providerParameters.get(0); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("name", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + QueryParameter queryParameter = (QueryParameter) parameter; + Assert.assertEquals("string", queryParameter.getType()); + parameter = providerParameters.get(1); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("age", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + queryParameter = (QueryParameter) parameter; + Assert.assertEquals("integer", queryParameter.getType()); + Assert.assertEquals("int32", queryParameter.getFormat()); + } + + /** + * Map and List param is not supported + */ + @Test + public void processOnUnsupportedParam() throws NoSuchMethodException { + final SwaggerGenerator swaggerGenerator = new SwaggerGenerator(Mockito.mock(SwaggerGeneratorContext.class), + TestProvider.class); + final Method providerMethod = TestProvider.class.getDeclaredMethod("testUnsupportedParamType", + int.class, List.class, Map.class); + final OperationGenerator operationGenerator = new OperationGenerator(swaggerGenerator, providerMethod); + + try { + new SpringmvcDefaultParameterProcessor().process(operationGenerator, 1); + fail("an error is expected!"); + } catch (Error e) { + Assert.assertEquals( + "cannot process parameter [integerList], method=org.apache.servicecomb.swagger.generator.springmvc" + + ".processor.parameter.SpringmvcDefaultParameterProcessorTest$TestProvider:testUnsupportedParamType, " + + "paramIdx=1, type=java.util.List<org.apache.servicecomb.swagger.generator.springmvc.processor.parameter" + + ".SpringmvcDefaultParameterProcessorTest$TestParam>", + e.getMessage()); + } + try { + new SpringmvcDefaultParameterProcessor().process(operationGenerator, 2); + fail("an error is expected!"); + } catch (Error e) { + Assert.assertEquals( + "cannot process parameter [stringMap], method=org.apache.servicecomb.swagger.generator.springmvc" + + ".processor.parameter.SpringmvcDefaultParameterProcessorTest$TestProvider:testUnsupportedParamType, " + + "paramIdx=2, type=java.util.Map<java.lang.String, java.lang.String>", + e.getMessage()); + } + } + + private OperationGenerator mockOperationGenerator(String providerParamName, String path, Class<?>... classes) + throws NoSuchMethodException { + final SwaggerGenerator swaggerGenerator = new SwaggerGenerator(Mockito.mock(SwaggerGeneratorContext.class), + TestProvider.class); + final Method providerMethod = TestProvider.class + .getDeclaredMethod(providerParamName, classes); + final OperationGenerator operationGenerator = new OperationGenerator(swaggerGenerator, providerMethod); + Deencapsulation.setField(operationGenerator, "path", path); + return operationGenerator; + } + + static class TestProvider { + public String testSimpleParam(String strParam) { + return strParam; + } + + public String testObjectParam(TestParam objParam) { + return objParam.toString(); + } + + public String testUnsupportedParamType(int i, List<TestParam> integerList, Map<String, String> stringMap) { + return null; + } + } + + static class TestParam { + private String name; + + private int age; + + public String getName() { + return name; + } + + public TestParam setName(String name) { + this.name = name; + return this; + } + + public int getAge() { + return age; + } + + public TestParam setAge(int age) { + this.age = age; + return this; + } + } +} \ No newline at end of file diff --git a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultSimpleParameterProcessorTest.java b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultSimpleParameterProcessorTest.java new file mode 100644 index 0000000..dd29928 --- /dev/null +++ b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/SpringmvcDefaultSimpleParameterProcessorTest.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.swagger.generator.springmvc.processor.parameter; + +import java.lang.reflect.Method; +import java.util.List; + +import org.apache.servicecomb.swagger.generator.core.OperationGenerator; +import org.apache.servicecomb.swagger.generator.core.SwaggerGenerator; +import org.apache.servicecomb.swagger.generator.core.SwaggerGeneratorContext; +import org.apache.servicecomb.swagger.generator.springmvc.processor.parameter.SpringmvcDefaultParameterProcessorTest.TestProvider; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import io.swagger.models.parameters.Parameter; +import io.swagger.models.parameters.QueryParameter; + +public class SpringmvcDefaultSimpleParameterProcessorTest { + @Test + public void process() throws NoSuchMethodException { + final SwaggerGenerator swaggerGenerator = new SwaggerGenerator(Mockito.mock(SwaggerGeneratorContext.class), + TestProvider.class); + final Method providerMethod = TestProvider.class.getDeclaredMethod("testSimpleParam", String.class); + final OperationGenerator operationGenerator = new OperationGenerator(swaggerGenerator, providerMethod); + + new SpringmvcDefaultSimpleParameterProcessor().process(operationGenerator, 0); + + final List<Parameter> providerParameters = operationGenerator.getProviderParameters(); + Assert.assertEquals(1, providerParameters.size()); + Parameter parameter = providerParameters.get(0); + Assert.assertEquals(QueryParameter.class, parameter.getClass()); + Assert.assertEquals("strParam", parameter.getName()); + Assert.assertEquals("query", parameter.getIn()); + QueryParameter queryParameter = (QueryParameter) parameter; + Assert.assertEquals("string", queryParameter.getType()); + } +}