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 3590a03b34aae667c00fd12419d6c0667f1c4ebc Author: yaohaishi <yaohai...@huawei.com> AuthorDate: Sat Jul 28 18:28:37 2018 +0800 [SCB-777] refactor ProducerArgumentsMapperFactory and add BeanParamMapper --- swagger/swagger-invocation/invocation-core/pom.xml | 1 - .../swagger/engine/SwaggerEnvironment.java | 26 ++- .../arguments/ArgumentsMapperFactory.java | 4 +- .../invocation/arguments/ProviderParameter.java | 14 ++ .../JaxRSProducerArgumentsMapperFactory.java | 147 +++++++++++++ .../producer/ProducerArgumentsMapperFactory.java | 96 ++++----- .../producer/ProducerBeanParamMapper.java | 62 ++++++ .../SpringMVCProducerArgumentsMapperFactory.java | 94 +++++++++ .../servicecomb/engine/TestSwaggerEnvironment.java | 77 ------- .../swagger/engine/TestSwaggerEnvironment.java | 121 +++++++++++ .../JaxRSProducerArgumentsMapperFactoryTest.java | 229 +++++++++++++++++++++ 11 files changed, 730 insertions(+), 141 deletions(-) diff --git a/swagger/swagger-invocation/invocation-core/pom.xml b/swagger/swagger-invocation/invocation-core/pom.xml index b1b2673..864ce08 100644 --- a/swagger/swagger-invocation/invocation-core/pom.xml +++ b/swagger/swagger-invocation/invocation-core/pom.xml @@ -35,7 +35,6 @@ <dependency> <groupId>org.apache.servicecomb</groupId> <artifactId>swagger-generator-jaxrs</artifactId> - <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java index e0ba98f..42852c1 100644 --- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java +++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java @@ -17,7 +17,9 @@ package org.apache.servicecomb.swagger.engine; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.inject.Inject; @@ -39,6 +41,7 @@ import org.apache.servicecomb.swagger.invocation.response.producer.ProducerRespo import org.apache.servicecomb.swagger.invocation.response.producer.ProducerResponseMapperFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import io.swagger.annotations.ApiOperation; @@ -51,9 +54,15 @@ public class SwaggerEnvironment { @Inject protected CompositeSwaggerGeneratorContext compositeSwaggerGeneratorContext; + /** + * default producerArgumentsFactory + */ @Inject private ProducerArgumentsMapperFactory producerArgumentsFactory; + @Autowired + private List<ProducerArgumentsMapperFactory> producerArgumentsMapperFactoryList = new ArrayList<>(0); + private ResponseMapperFactorys<ProducerResponseMapper> producerResponseMapperFactorys = new ResponseMapperFactorys<>(ProducerResponseMapperFactory.class); @@ -174,7 +183,8 @@ public class SwaggerEnvironment { config.setSwaggerOperation(swaggerOperationMap.get(methodName)); config.setSwaggerGeneratorContext(compositeSwaggerGeneratorContext.selectContext(producerCls)); - ProducerArgumentsMapper argsMapper = producerArgumentsFactory.createArgumentsMapper(config); + ProducerArgumentsMapperFactory argumentsMapperFactory = selectProducerArgumentsMapperFactory(config); + ProducerArgumentsMapper argsMapper = argumentsMapperFactory.createArgumentsMapper(config); ProducerResponseMapper responseMapper = producerResponseMapperFactorys.createResponseMapper( swaggerMethod.getGenericReturnType(), producerMethod.getGenericReturnType()); @@ -194,6 +204,20 @@ public class SwaggerEnvironment { return producer; } + ProducerArgumentsMapperFactory selectProducerArgumentsMapperFactory(ArgumentsMapperConfig config) { + ProducerArgumentsMapperFactory argumentsMapperFactory = null; + for (ProducerArgumentsMapperFactory producerArgumentsMapperFactory : this.producerArgumentsMapperFactoryList) { + if (producerArgumentsMapperFactory.canProcess(config)) { + argumentsMapperFactory = producerArgumentsMapperFactory; + break; + } + } + if (null == argumentsMapperFactory) { + argumentsMapperFactory = this.producerArgumentsFactory; + } + return argumentsMapperFactory; + } + private Map<String, Method> retrieveVisibleMethods(Class<?> clazz) { Map<String, Method> visibleMethods = new HashMap<>(); for (Method method : clazz.getMethods()) { diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ArgumentsMapperFactory.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ArgumentsMapperFactory.java index 3d86a49..001f808 100644 --- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ArgumentsMapperFactory.java +++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ArgumentsMapperFactory.java @@ -125,6 +125,7 @@ public abstract class ArgumentsMapperFactory<T> { protected List<ProviderParameter> collectContextArgumentsMapper(ArgumentsMapperConfig config) { List<ProviderParameter> providerNormalParams = new ArrayList<>(); + final Annotation[][] parameterAnnotations = config.getProviderMethod().getParameterAnnotations(); Type[] providerParameterTypes = config.getProviderMethod().getGenericParameterTypes(); for (int providerIdx = 0; providerIdx < providerParameterTypes.length; providerIdx++) { Type parameterType = providerParameterTypes[providerIdx]; @@ -136,7 +137,8 @@ public abstract class ArgumentsMapperFactory<T> { } ProviderParameter pp = new ProviderParameter(providerIdx, parameterType, - retrieveVisibleParamName(config.getProviderMethod(), providerIdx)); + retrieveVisibleParamName(config.getProviderMethod(), providerIdx)) + .setAnnotations(parameterAnnotations[providerIdx]); providerNormalParams.add(pp); } diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ProviderParameter.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ProviderParameter.java index 299c02f..988efc1 100644 --- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ProviderParameter.java +++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ProviderParameter.java @@ -16,7 +16,9 @@ */ package org.apache.servicecomb.swagger.invocation.arguments; +import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import java.util.Arrays; public class ProviderParameter { private int index; @@ -28,6 +30,8 @@ public class ProviderParameter { */ private String name; + private Annotation[] annotations; + public ProviderParameter(int index, Type type, String name) { this.index = index; this.type = type; @@ -61,12 +65,22 @@ public class ProviderParameter { return this; } + public Annotation[] getAnnotations() { + return annotations; + } + + public ProviderParameter setAnnotations(Annotation[] annotations) { + this.annotations = annotations; + return this; + } + @Override public String toString() { final StringBuilder sb = new StringBuilder("ProviderParameter{"); sb.append("index=").append(index); sb.append(", type=").append(type); sb.append(", name='").append(name).append('\''); + sb.append(", annotations=").append(Arrays.toString(annotations)); sb.append('}'); return sb.toString(); } diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactory.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactory.java new file mode 100644 index 0000000..d0b84cd --- /dev/null +++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactory.java @@ -0,0 +1,147 @@ +/* + * 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.invocation.arguments.producer; + +import static org.apache.servicecomb.swagger.generator.jaxrs.processor.annotation.BeanParamAnnotationProcessor.SETTER_METHOD_PREFIX; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import javax.ws.rs.BeanParam; + +import org.apache.servicecomb.swagger.generator.jaxrs.processor.annotation.BeanParamAnnotationProcessor; +import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper; +import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig; +import org.apache.servicecomb.swagger.invocation.arguments.ProviderParameter; +import org.springframework.stereotype.Component; + +import io.swagger.models.parameters.Parameter; + +@Component +public class JaxRSProducerArgumentsMapperFactory extends ProducerArgumentsMapperFactory { + @Override + public boolean canProcess(ArgumentsMapperConfig config) { + return config.getSwaggerGeneratorContext().getClass().getCanonicalName().equals( + "org.apache.servicecomb.swagger.generator.jaxrs.JaxrsSwaggerGeneratorContext"); + } + + @Override + protected Set<String> findAggregatedParamNames(Map<String, ProviderParameter> providerParamMap, + Map<String, ParamWrapper<Parameter>> swaggerParamMap) { + Set<String> aggregatedParamNames = new HashSet<>(); + for (Entry<String, ProviderParameter> providerParameterEntry : providerParamMap.entrySet()) { + if (null == providerParameterEntry.getValue().getAnnotations()) { + // request body may have no annotation + continue; + } + for (Annotation annotation : providerParameterEntry.getValue().getAnnotations()) { + if (annotation instanceof BeanParam) { + aggregatedParamNames.add(providerParameterEntry.getKey()); + } + } + } + + return aggregatedParamNames; + } + + @Override + protected void generateAggregatedParamMapper(ArgumentsMapperConfig config, + Map<String, ProviderParameter> providerParamMap, Map<String, ParamWrapper<Parameter>> swaggerParamMap, + Set<String> aggregatedParamNames) { + for (String aggregatedProducerParamName : aggregatedParamNames) { + ProviderParameter aggregatedParam = providerParamMap.get(aggregatedProducerParamName); + // producer param name -> swagger param name + Map<String, String> producerToSwaggerParamNameMapper = getProducerToSwaggerParamNameMap(aggregatedParam); + // producer param name -> swagger param index + Map<String, Integer> producerNameToSwaggerIndexMap = new HashMap<>(producerToSwaggerParamNameMapper.size()); + for (Entry<String, String> producerSwaggerNameMapEntry : producerToSwaggerParamNameMapper.entrySet()) { + producerNameToSwaggerIndexMap.put( + producerSwaggerNameMapEntry.getKey(), + swaggerParamMap.get(producerSwaggerNameMapEntry.getValue()).getIndex()); + } + + // create&add aggregated param mapper + ArgumentMapper mapper = new ProducerBeanParamMapper(producerNameToSwaggerIndexMap, + aggregatedParam.getIndex(), + aggregatedParam.getType()); + config.addArgumentMapper(mapper); + } + } + + /** + * <pre> + * public class AggregatedParam { + * \@PathParam("pathSwaggerParam") + * private String pathProducerParam; + * + * private String queryProducerParam; + * + * \@QueryParam(value = "querySwaggerParam") + * public void setQueryProducerParam(String queryParam) { + * this.queryProducerParam = queryParam; + * } + * } + * </pre> + * Given a BeanParam like above, will return a map like below: + * { + * "pathProducerParam" -> "pathSwaggerParam", + * "queryProducerParam" -> "querySwaggerParam" + * } + */ + private Map<String, String> getProducerToSwaggerParamNameMap(ProviderParameter aggregatedParam) { + Map<String, String> producerToSwaggerParamNameMapper = new HashMap<>(); + Class<?> aggregatedParamClazz = (Class<?>) aggregatedParam.getType(); + // map those params defined by BeanParam fields + for (Field field : aggregatedParamClazz.getDeclaredFields()) { + for (Annotation fieldAnnotation : field.getAnnotations()) { + if (BeanParamAnnotationProcessor.SUPPORTED_PARAM_ANNOTATIONS.contains(fieldAnnotation.annotationType())) { + producerToSwaggerParamNameMapper.put( + field.getName(), + retrieveVisibleParamName(fieldAnnotation)); + break; + } + } + } + // map those params defined by setter methods + for (Method method : aggregatedParamClazz.getDeclaredMethods()) { + final String methodName = method.getName(); + if (!methodName.startsWith(SETTER_METHOD_PREFIX)) { + // only process setter methods + continue; + } + // There should be one and only one param in a setter method + for (Annotation setterAnnotation : method.getAnnotations()) { + if (BeanParamAnnotationProcessor.SUPPORTED_PARAM_ANNOTATIONS.contains(setterAnnotation.annotationType())) { + producerToSwaggerParamNameMapper.put( + methodName.substring( // setParamName() -> "paramName" + SETTER_METHOD_PREFIX.length(), SETTER_METHOD_PREFIX.length() + 1).toLowerCase() + + methodName.substring(SETTER_METHOD_PREFIX.length() + 1), + retrieveVisibleParamName(setterAnnotation)); + break; + } + } + } + return producerToSwaggerParamNameMapper; + } +} diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperFactory.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperFactory.java index 204dea9..0a59aa6 100644 --- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperFactory.java +++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperFactory.java @@ -18,8 +18,8 @@ package org.apache.servicecomb.swagger.invocation.arguments.producer; import java.lang.reflect.Type; +import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -27,7 +27,7 @@ import java.util.Set; import javax.inject.Inject; -import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils; +import org.apache.servicecomb.swagger.generator.rest.RestSwaggerGeneratorContext; import org.apache.servicecomb.swagger.invocation.InvocationType; import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper; import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig; @@ -39,16 +39,15 @@ import org.apache.servicecomb.swagger.invocation.converter.Converter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; -import io.swagger.converter.ModelConverters; import io.swagger.models.parameters.Parameter; -import io.swagger.models.parameters.QueryParameter; -import io.swagger.models.properties.Property; -import io.swagger.models.properties.RefProperty; @Component +@Primary public class ProducerArgumentsMapperFactory extends ArgumentsMapperFactory<ProducerArgumentsMapper> { + private static final Logger LOGGER = LoggerFactory.getLogger(ProducerArgumentsMapperFactory.class); public ProducerArgumentsMapperFactory() { @@ -69,46 +68,50 @@ public class ProducerArgumentsMapperFactory extends ArgumentsMapperFactory<Produ config.getProviderMethod().getParameterCount()); } + public boolean canProcess(ArgumentsMapperConfig config) { + return false; + } + @Override protected void collectSwaggerArgumentsMapper(ArgumentsMapperConfig config, List<ProviderParameter> providerNormalParams) { - if (!config.getSwaggerGeneratorContext().getClass().getCanonicalName().equals( - "org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGeneratorContext")) { - // if this is not a SpringMVC style provider operation, there is no need to consider query object param + if (!RestSwaggerGeneratorContext.class.isInstance(config.getSwaggerGeneratorContext())) { + // POJO style provider does not support aggregated param super.collectSwaggerArgumentsMapper(config, providerNormalParams); return; } + // JAX-RS and SpringMVC style provider support aggregated param, i.e. @BeanParam and query object, respectively Map<String, ProviderParameter> providerParamMap = getProviderParamMap(providerNormalParams); Map<String, ParamWrapper<Parameter>> swaggerParamMap = getSwaggerParamMap(config); - Set<String> queryObjectNames = findSpringMvcQueryObject(providerParamMap, swaggerParamMap); - if (queryObjectNames.isEmpty()) { - // there is no query object param, run as 1-to-1 param mapping mode + Set<String> aggregatedParamNames = findAggregatedParamNames(providerParamMap, swaggerParamMap); + if (aggregatedParamNames.isEmpty()) { + // there is no aggregated param, run as 1-to-1 param mapping mode super.collectSwaggerArgumentsMapper(config, providerNormalParams); return; } - // There is at lease one query object param, so the param mapping mode becomes to M-to-N + // There is at lease one aggregated param, so the param mapping mode becomes to M-to-N // try to map params by name - generateParamMapperByName(config, providerParamMap, swaggerParamMap, queryObjectNames); + generateParamMapperByName(config, providerParamMap, swaggerParamMap, aggregatedParamNames); } private void generateParamMapperByName(ArgumentsMapperConfig config, Map<String, ProviderParameter> providerParamMap, - Map<String, ParamWrapper<Parameter>> swaggerParamMap, Set<String> queryObjectNames) { - LOGGER.info("mapping query object params: [{}]", queryObjectNames); - generateObjectQueryParamMapper(config, providerParamMap, swaggerParamMap, queryObjectNames); - generateDefaultParamMapper(config, providerParamMap, swaggerParamMap, queryObjectNames); + Map<String, ParamWrapper<Parameter>> swaggerParamMap, Set<String> aggregatedParamNames) { + LOGGER.info("mapping aggregated params: [{}]", aggregatedParamNames); + generateAggregatedParamMapper(config, providerParamMap, swaggerParamMap, aggregatedParamNames); + generateDefaultParamMapper(config, providerParamMap, swaggerParamMap, aggregatedParamNames); } /** * Generate default argument mappers. One swagger argument is mapped to one producer argument. */ private void generateDefaultParamMapper(ArgumentsMapperConfig config, Map<String, ProviderParameter> providerParamMap, - Map<String, ParamWrapper<Parameter>> swaggerParamMap, Set<String> queryObjectNames) { + Map<String, ParamWrapper<Parameter>> swaggerParamMap, Set<String> aggregatedParamNames) { Type[] swaggerParamTypes = config.getSwaggerMethod().getGenericParameterTypes(); for (Entry<String, ProviderParameter> providerParamEntry : providerParamMap.entrySet()) { - if (queryObjectNames.contains(providerParamEntry.getKey())) { + if (aggregatedParamNames.contains(providerParamEntry.getKey())) { continue; } @@ -122,29 +125,17 @@ public class ProducerArgumentsMapperFactory extends ArgumentsMapperFactory<Produ } /** - * Generate argument mappers for query object params. Collect all query params as json and map them to object param. + * Generate argument mappers for aggregated params. + * Collect related swagger params and map them to an aggregated param. + * It's implemented by SpringMVC and JAX-RS. */ - private void generateObjectQueryParamMapper(ArgumentsMapperConfig config, + protected void generateAggregatedParamMapper(ArgumentsMapperConfig config, Map<String, ProviderParameter> providerParamMap, Map<String, ParamWrapper<Parameter>> swaggerParamMap, - Set<String> queryObjectNames) { - // collect all query params - Map<String, Integer> querySwaggerParamsIndex = new HashMap<>(); - for (Entry<String, ParamWrapper<Parameter>> wrapperEntry : swaggerParamMap.entrySet()) { - if (wrapperEntry.getValue().getParam() instanceof QueryParameter) { - querySwaggerParamsIndex.put(wrapperEntry.getKey(), wrapperEntry.getValue().getIndex()); - } - } - // create mapper for each query objects - for (String queryObjectName : queryObjectNames) { - final ProviderParameter providerParameter = providerParamMap.get(queryObjectName); - ArgumentMapper mapper = new ProducerSpringMVCQueryObjectMapper(querySwaggerParamsIndex, - providerParameter.getIndex(), - providerParameter.getType()); - config.addArgumentMapper(mapper); - } + Set<String> aggregatedParamNames) { + // do nothing, not supported by default } - private Map<String, ParamWrapper<Parameter>> getSwaggerParamMap(ArgumentsMapperConfig config) { + protected Map<String, ParamWrapper<Parameter>> getSwaggerParamMap(ArgumentsMapperConfig config) { Map<String, ParamWrapper<Parameter>> swaggerParamMap = new HashMap<>(config.getSwaggerOperation().getParameters().size()); List<Parameter> parameters = config.getSwaggerOperation().getParameters(); @@ -155,7 +146,7 @@ public class ProducerArgumentsMapperFactory extends ArgumentsMapperFactory<Produ return swaggerParamMap; } - private Map<String, ProviderParameter> getProviderParamMap(List<ProviderParameter> providerNormalParams) { + protected Map<String, ProviderParameter> getProviderParamMap(List<ProviderParameter> providerNormalParams) { Map<String, ProviderParameter> providerParamMap = new HashMap<>(providerNormalParams.size()); providerNormalParams.forEach( providerParameter -> providerParamMap.put(providerParameter.getName(), providerParameter)); @@ -163,29 +154,12 @@ public class ProducerArgumentsMapperFactory extends ArgumentsMapperFactory<Produ } /** - * Find all query object params - * @return the names of the query object params + * Find all aggregated params + * @return the names of the aggregated params */ - private Set<String> findSpringMvcQueryObject(Map<String, ProviderParameter> providerParamMap, + protected Set<String> findAggregatedParamNames(Map<String, ProviderParameter> providerParamMap, Map<String, ParamWrapper<Parameter>> swaggerParamMap) { - // find all reference type producer params, and exclude body param - Set<String> queryObjectSet = new HashSet<>(); - - for (Entry<String, ProviderParameter> paramEntry : providerParamMap.entrySet()) { - Type paramType = paramEntry.getValue().getType(); - Property property = ModelConverters.getInstance().readAsProperty(paramType); - if (RefProperty.class.isInstance(property)) { - queryObjectSet.add(paramEntry.getKey()); - } - } - - for (Entry<String, ParamWrapper<Parameter>> paramEntry : swaggerParamMap.entrySet()) { - if (ParamUtils.isRealBodyParameter(paramEntry.getValue().getParam())) { - queryObjectSet.remove(paramEntry.getKey()); - } - } - - return queryObjectSet; + return Collections.emptySet(); } @Override diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapper.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapper.java new file mode 100644 index 0000000..b72b7c9 --- /dev/null +++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapper.java @@ -0,0 +1,62 @@ +/* + * 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.invocation.arguments.producer; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; +import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper; +import org.apache.servicecomb.swagger.invocation.converter.Converter; +import org.apache.servicecomb.swagger.invocation.converter.impl.ConverterCommon; + +public class ProducerBeanParamMapper implements ArgumentMapper { + + private int producerIdx; + + private Map<String, Integer> swaggerParamIndexMap; + + private Converter converter; + + /** + * @param producerNameToSwaggerIndexMap name of the fields & setters defined in @BeanParam parameter -> swagger param index + * @param producerIdx index of producer param + * @param producerParamType type of producer param + */ + public ProducerBeanParamMapper(Map<String, Integer> producerNameToSwaggerIndexMap, int producerIdx, + Type producerParamType) { + this.producerIdx = producerIdx; + this.swaggerParamIndexMap = new HashMap<>(); + this.swaggerParamIndexMap.putAll(producerNameToSwaggerIndexMap); + converter = new ConverterCommon(producerParamType); + } + + @Override + public void mapArgument(SwaggerInvocation invocation, Object[] producerArguments) { + Map<String, Object> jsonMap = new HashMap<>(swaggerParamIndexMap.size()); + + for (Entry<String, Integer> swaggerIndexEntry : swaggerParamIndexMap.entrySet()) { + jsonMap.put(swaggerIndexEntry.getKey(), invocation.getSwaggerArgument(swaggerIndexEntry.getValue())); + } + + final Object producerParam = converter.convert(jsonMap); + producerArguments[producerIdx] = producerParam; + } +} diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/SpringMVCProducerArgumentsMapperFactory.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/SpringMVCProducerArgumentsMapperFactory.java new file mode 100644 index 0000000..f7d1eda --- /dev/null +++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/SpringMVCProducerArgumentsMapperFactory.java @@ -0,0 +1,94 @@ +/* + * 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.invocation.arguments.producer; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils; +import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper; +import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig; +import org.apache.servicecomb.swagger.invocation.arguments.ProviderParameter; +import org.springframework.stereotype.Component; + +import io.swagger.converter.ModelConverters; +import io.swagger.models.parameters.Parameter; +import io.swagger.models.parameters.QueryParameter; +import io.swagger.models.properties.Property; +import io.swagger.models.properties.RefProperty; + +@Component +public class SpringMVCProducerArgumentsMapperFactory extends ProducerArgumentsMapperFactory { + + @Override + public boolean canProcess(ArgumentsMapperConfig config) { + return config.getSwaggerGeneratorContext().getClass().getCanonicalName().equals( + "org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGeneratorContext"); + } + + /** + * Find all query object params + * @return the names of the query object params + */ + @Override + protected Set<String> findAggregatedParamNames(Map<String, ProviderParameter> providerParamMap, + Map<String, ParamWrapper<Parameter>> swaggerParamMap) { + // find all reference type producer params, and exclude body param + Set<String> queryObjectSet = new HashSet<>(); + + for (Entry<String, ProviderParameter> paramEntry : providerParamMap.entrySet()) { + Type paramType = paramEntry.getValue().getType(); + Property property = ModelConverters.getInstance().readAsProperty(paramType); + if (RefProperty.class.isInstance(property)) { + queryObjectSet.add(paramEntry.getKey()); + } + } + + for (Entry<String, ParamWrapper<Parameter>> paramEntry : swaggerParamMap.entrySet()) { + if (ParamUtils.isRealBodyParameter(paramEntry.getValue().getParam())) { + queryObjectSet.remove(paramEntry.getKey()); + } + } + + return queryObjectSet; + } + + protected void generateAggregatedParamMapper(ArgumentsMapperConfig config, + Map<String, ProviderParameter> providerParamMap, Map<String, ParamWrapper<Parameter>> swaggerParamMap, + Set<String> aggregatedParamNames) { + // collect all query params + Map<String, Integer> querySwaggerParamsIndex = new HashMap<>(); + for (Entry<String, ParamWrapper<Parameter>> wrapperEntry : swaggerParamMap.entrySet()) { + if (wrapperEntry.getValue().getParam() instanceof QueryParameter) { + querySwaggerParamsIndex.put(wrapperEntry.getKey(), wrapperEntry.getValue().getIndex()); + } + } + // create mapper for each query objects + for (String queryObjectName : aggregatedParamNames) { + final ProviderParameter providerParameter = providerParamMap.get(queryObjectName); + ArgumentMapper mapper = new ProducerSpringMVCQueryObjectMapper(querySwaggerParamsIndex, + providerParameter.getIndex(), + providerParameter.getType()); + config.addArgumentMapper(mapper); + } + } +} diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/engine/TestSwaggerEnvironment.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/engine/TestSwaggerEnvironment.java deleted file mode 100644 index 82c6ad4..0000000 --- a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/engine/TestSwaggerEnvironment.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.engine; - -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsNull.notNullValue; -import static org.hamcrest.core.IsNull.nullValue; -import static org.junit.Assert.assertThat; - -import org.apache.servicecomb.common.javassist.JavassistUtils; -import org.apache.servicecomb.swagger.engine.SwaggerConsumer; -import org.apache.servicecomb.swagger.engine.SwaggerProducer; -import org.apache.servicecomb.swagger.invocation.models.ProducerImpl; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestSwaggerEnvironment { - private static SwaggerEnvironmentForTest env = new SwaggerEnvironmentForTest(); - - private static SwaggerProducer producer; - - @BeforeClass - public static void init() { - producer = env.createProducer(new ProducerImpl()); - } - - @AfterClass - public static void tearDown() { - JavassistUtils.clearByClassLoader(env.getClassLoader()); - } - - @Test - public void ableToFindVisibleMethod() { - assertThat(producer.findOperation("visibleMethod"), is(notNullValue())); - } - - @Test - public void unableToFindHiddenMethod() { - assertThat(producer.findOperation("hiddenMethod"), is(nullValue())); - } - - interface ConsumerIntf { - void exist(); - - void notExist(); - } - - interface ContractIntf { - void exist(); - } - - @Test - public void createConsumer_consumerMethodSetBigger() { - SwaggerConsumer swaggerConsumer = env.getSwaggerEnvironment() - .createConsumer(ConsumerIntf.class, ContractIntf.class); - - Assert.assertNotNull(swaggerConsumer.findOperation("exist")); - Assert.assertNull(swaggerConsumer.findOperation("notExist")); - } -} diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/engine/TestSwaggerEnvironment.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/engine/TestSwaggerEnvironment.java new file mode 100644 index 0000000..0a888cc --- /dev/null +++ b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/engine/TestSwaggerEnvironment.java @@ -0,0 +1,121 @@ +/* + * 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.engine; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.servicecomb.common.javassist.JavassistUtils; +import org.apache.servicecomb.engine.SwaggerEnvironmentForTest; +import org.apache.servicecomb.swagger.generator.jaxrs.JaxrsSwaggerGeneratorContext; +import org.apache.servicecomb.swagger.generator.pojo.PojoSwaggerGeneratorContext; +import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig; +import org.apache.servicecomb.swagger.invocation.arguments.producer.JaxRSProducerArgumentsMapperFactory; +import org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerArgumentsMapperFactory; +import org.apache.servicecomb.swagger.invocation.arguments.producer.SpringMVCProducerArgumentsMapperFactory; +import org.apache.servicecomb.swagger.invocation.models.ProducerImpl; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import mockit.Deencapsulation; + +public class TestSwaggerEnvironment { + private static SwaggerEnvironmentForTest env = new SwaggerEnvironmentForTest(); + + private static SwaggerProducer producer; + + private static ProducerArgumentsMapperFactory defaultProducerArgumentsMapperFactory; + + @BeforeClass + public static void init() { + producer = env.createProducer(new ProducerImpl()); + defaultProducerArgumentsMapperFactory = new ProducerArgumentsMapperFactory(); + List<ProducerArgumentsMapperFactory> producerArgumentsMapperFactoryList = new ArrayList<>(); + producerArgumentsMapperFactoryList.add(new JaxRSProducerArgumentsMapperFactory()); + producerArgumentsMapperFactoryList.add(new SpringMVCProducerArgumentsMapperFactory()); + producerArgumentsMapperFactoryList.add(new ProducerArgumentsMapperFactory()); + + Deencapsulation.setField( + env.getSwaggerEnvironment(), "producerArgumentsFactory", defaultProducerArgumentsMapperFactory); + Deencapsulation.setField( + env.getSwaggerEnvironment(), "producerArgumentsMapperFactoryList", producerArgumentsMapperFactoryList); + } + + @AfterClass + public static void tearDown() { + JavassistUtils.clearByClassLoader(env.getClassLoader()); + } + + @Test + public void ableToFindVisibleMethod() { + assertThat(producer.findOperation("visibleMethod"), is(notNullValue())); + } + + @Test + public void unableToFindHiddenMethod() { + assertThat(producer.findOperation("hiddenMethod"), is(nullValue())); + } + + interface ConsumerIntf { + void exist(); + + void notExist(); + } + + interface ContractIntf { + void exist(); + } + + @Test + public void createConsumer_consumerMethodSetBigger() { + SwaggerConsumer swaggerConsumer = env.getSwaggerEnvironment() + .createConsumer(ConsumerIntf.class, ContractIntf.class); + + Assert.assertNotNull(swaggerConsumer.findOperation("exist")); + Assert.assertNull(swaggerConsumer.findOperation("notExist")); + } + + @Test + public void selectProducerArgumentsMapperFactory() { + final ArgumentsMapperConfig config = new ArgumentsMapperConfig(); + config.setSwaggerGeneratorContext(new JaxrsSwaggerGeneratorContext()); + + final ProducerArgumentsMapperFactory producerArgumentsMapperFactory = env.getSwaggerEnvironment() + .selectProducerArgumentsMapperFactory(config); + + Assert.assertEquals(JaxRSProducerArgumentsMapperFactory.class, producerArgumentsMapperFactory.getClass()); + } + + @Test + public void selectProducerArgumentsMapperFactoryOnReturnDefault() { + final ArgumentsMapperConfig config = new ArgumentsMapperConfig(); + config.setSwaggerGeneratorContext(new PojoSwaggerGeneratorContext()); + + final ProducerArgumentsMapperFactory producerArgumentsMapperFactory = env.getSwaggerEnvironment() + .selectProducerArgumentsMapperFactory(config); + + Assert.assertSame(defaultProducerArgumentsMapperFactory, producerArgumentsMapperFactory); + } +} diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactoryTest.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactoryTest.java new file mode 100644 index 0000000..7519203 --- /dev/null +++ b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactoryTest.java @@ -0,0 +1,229 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.swagger.invocation.arguments.producer; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.Part; +import javax.ws.rs.BeanParam; +import javax.ws.rs.CookieParam; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.FormParam; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; + +import org.apache.servicecomb.swagger.generator.jaxrs.JaxrsSwaggerGeneratorContext; +import org.apache.servicecomb.swagger.generator.pojo.PojoSwaggerGeneratorContext; +import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig; +import org.apache.servicecomb.swagger.invocation.arguments.ProviderParameter; +import org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerArgumentsMapperFactory.ParamWrapper; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; + +import io.swagger.models.parameters.CookieParameter; +import io.swagger.models.parameters.FormParameter; +import io.swagger.models.parameters.HeaderParameter; +import io.swagger.models.parameters.Parameter; +import io.swagger.models.parameters.PathParameter; +import io.swagger.models.parameters.QueryParameter; +import mockit.Deencapsulation; + +public class JaxRSProducerArgumentsMapperFactoryTest { + + private final JaxRSProducerArgumentsMapperFactory producerArgumentsMapperFactory = new JaxRSProducerArgumentsMapperFactory(); + + @Test + public void canProcess() { + ArgumentsMapperConfig argumentsMapperConfig = new ArgumentsMapperConfig(); + + argumentsMapperConfig.setSwaggerGeneratorContext(new JaxrsSwaggerGeneratorContext()); + Assert.assertTrue(producerArgumentsMapperFactory.canProcess(argumentsMapperConfig)); + + argumentsMapperConfig.setSwaggerGeneratorContext(new PojoSwaggerGeneratorContext()); + Assert.assertFalse(producerArgumentsMapperFactory.canProcess(argumentsMapperConfig)); + } + + @Test + public void findAggregatedParamNames() throws NoSuchMethodException { + Map<String, ProviderParameter> providerParamMap = new HashMap<>(); + providerParamMap.put("qqq", new ProviderParameter(1, String.class, "qqq")); + Method aggregatedTestParamMethod = AggregatedParamProvider.class + .getMethod("aggregatedParamTest", AggregatedTestParam.class); + Annotation beanParamAnnotation = aggregatedTestParamMethod.getParameterAnnotations()[0][0]; + providerParamMap.put("aggregatedTestParam", + new ProviderParameter(0, AggregatedTestParam.class, "aggregatedTestParam") + .setAnnotations(new Annotation[] {beanParamAnnotation})); + + Map<String, ParamWrapper<Parameter>> swaggerParamMap = new HashMap<>(); + Parameter swaggerParam = new PathParameter().name("pathSwaggerParam"); + swaggerParamMap.put("pathSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(0)); + swaggerParam = new HeaderParameter().name("headerSwaggerParam"); + swaggerParamMap.put("headerSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(1)); + swaggerParam = new CookieParameter().name("intSwaggerVal"); + swaggerParamMap.put("intSwaggerVal", new ParamWrapper<>(swaggerParam).setIndex(2)); + swaggerParam = new FormParameter().name("longSwaggerVal"); + swaggerParamMap.put("longSwaggerVal", new ParamWrapper<>(swaggerParam).setIndex(3)); + swaggerParam = new QueryParameter().name("querySwaggerParam"); + swaggerParamMap.put("querySwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(4)); + swaggerParam = new FormParameter().name("uploadSwaggerParam"); + swaggerParamMap.put("uploadSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(5)); + swaggerParam = new QueryParameter().name("qqq"); + swaggerParamMap.put("qqq", new ParamWrapper<>(swaggerParam).setIndex(6)); + + Set<String> aggregatedParamNames = producerArgumentsMapperFactory + .findAggregatedParamNames(providerParamMap, swaggerParamMap); + Assert.assertThat(aggregatedParamNames, Matchers.contains("aggregatedTestParam")); + } + + @Test + public void generateAggregatedParamMapper() throws NoSuchMethodException { + Map<String, ProviderParameter> providerParamMap = new HashMap<>(); + providerParamMap.put("qqq", new ProviderParameter(1, String.class, "qqq")); + Method aggregatedTestParamMethod = AggregatedParamProvider.class + .getMethod("aggregatedParamTest", AggregatedTestParam.class); + Annotation beanParamAnnotation = aggregatedTestParamMethod.getParameterAnnotations()[0][0]; + providerParamMap.put("aggregatedTestParam", + new ProviderParameter(0, AggregatedTestParam.class, "aggregatedTestParam") + .setAnnotations(new Annotation[] {beanParamAnnotation})); + + Map<String, ParamWrapper<Parameter>> swaggerParamMap = new HashMap<>(); + Parameter swaggerParam = new PathParameter().name("pathSwaggerParam"); + swaggerParamMap.put("pathSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(0)); + swaggerParam = new HeaderParameter().name("headerSwaggerParam"); + swaggerParamMap.put("headerSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(1)); + swaggerParam = new CookieParameter().name("intSwaggerVal"); + swaggerParamMap.put("intSwaggerVal", new ParamWrapper<>(swaggerParam).setIndex(2)); + swaggerParam = new FormParameter().name("longSwaggerVal"); + swaggerParamMap.put("longSwaggerVal", new ParamWrapper<>(swaggerParam).setIndex(3)); + swaggerParam = new QueryParameter().name("querySwaggerParam"); + swaggerParamMap.put("querySwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(4)); + swaggerParam = new FormParameter().name("uploadSwaggerParam"); + swaggerParamMap.put("uploadSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(5)); + swaggerParam = new QueryParameter().name("qqq"); + swaggerParamMap.put("qqq", new ParamWrapper<>(swaggerParam).setIndex(6)); + + Set<String> aggregatedParamNames = new HashSet<>(); + aggregatedParamNames.add("aggregatedTestParam"); + ArgumentsMapperConfig argumentsMapperConfig = new ArgumentsMapperConfig(); + producerArgumentsMapperFactory.generateAggregatedParamMapper( + argumentsMapperConfig, providerParamMap, swaggerParamMap, aggregatedParamNames); + + Assert.assertEquals(1, argumentsMapperConfig.getArgumentMapperList().size()); + Assert.assertEquals(ProducerBeanParamMapper.class, argumentsMapperConfig.getArgumentMapperList().get(0).getClass()); + ProducerBeanParamMapper producerBeanParamMapper = + (ProducerBeanParamMapper) argumentsMapperConfig.getArgumentMapperList().get(0); + Assert.assertEquals(Integer.valueOf(0), Deencapsulation.getField(producerBeanParamMapper, "producerIdx")); + Map<String, Integer> swaggerParamIndexMap = + Deencapsulation.getField(producerBeanParamMapper, "swaggerParamIndexMap"); + Assert.assertEquals(Integer.valueOf(0), swaggerParamIndexMap.get("pathParam")); + Assert.assertEquals(Integer.valueOf(1), swaggerParamIndexMap.get("headerParam")); + Assert.assertEquals(Integer.valueOf(2), swaggerParamIndexMap.get("intVal")); + Assert.assertEquals(Integer.valueOf(3), swaggerParamIndexMap.get("longVal")); + Assert.assertEquals(Integer.valueOf(4), swaggerParamIndexMap.get("q")); + Assert.assertEquals(Integer.valueOf(5), swaggerParamIndexMap.get("uploaded")); + } + + static class AggregatedParamProvider { + public String aggregatedParamTest(@BeanParam AggregatedTestParam aggregatedTestParam) { + return null; + } + } + + static class AggregatedTestParam { + @PathParam("pathSwaggerParam") + private String pathParam; + + private String queryParam; + + @DefaultValue("defaultHeader") + @HeaderParam(value = "headerSwaggerParam") + private String headerParam; + + @CookieParam("intSwaggerVal") + private int intVal; + + @FormParam("longSwaggerVal") + private long longVal; + + private Part uploaded; + + public String getPathParam() { + return pathParam; + } + + public AggregatedTestParam setPathParam(String pathParam) { + this.pathParam = pathParam; + return this; + } + + public String getQ() { + return queryParam; + } + + @DefaultValue("defaultQuery") + @QueryParam(value = "querySwaggerParam") + public AggregatedTestParam setQ(String queryParam) { + this.queryParam = queryParam; + return this; + } + + public String getHeaderParam() { + return headerParam; + } + + public AggregatedTestParam setHeaderParam(String headerParam) { + this.headerParam = headerParam; + return this; + } + + public int getIntVal() { + return intVal; + } + + public AggregatedTestParam setIntVal(int intVal) { + this.intVal = intVal; + return this; + } + + public long getLongVal() { + return longVal; + } + + public AggregatedTestParam setLongVal(long longVal) { + this.longVal = longVal; + return this; + } + + public Part getUploaded() { + return uploaded; + } + + @FormParam("uploadSwaggerParam") + public AggregatedTestParam setUploaded(Part uploaded) { + this.uploaded = uploaded; + return this; + } + } +} \ No newline at end of file