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());
+  }
+}

Reply via email to