diff --git a/src/main/java/com/knappsack/swagger4springweb/parser/ApiModelParser.java b/src/main/java/com/knappsack/swagger4springweb/parser/ApiModelParser.java index 2e87fe1..fdc27be 100644 --- a/src/main/java/com/knappsack/swagger4springweb/parser/ApiModelParser.java +++ b/src/main/java/com/knappsack/swagger4springweb/parser/ApiModelParser.java @@ -1,55 +1,24 @@ package com.knappsack.swagger4springweb.parser; -import com.knappsack.swagger4springweb.model.AnnotatedParameter; -import com.knappsack.swagger4springweb.util.AnnotationUtils; -import com.wordnik.swagger.converter.SwaggerSchemaConverter; +import com.knappsack.swagger4springweb.util.ApiUtils; import com.wordnik.swagger.model.Model; import org.springframework.web.bind.annotation.ResponseBody; -import scala.Option; import java.lang.reflect.Method; +import java.lang.reflect.Type; import java.util.HashMap; -import java.util.List; import java.util.Map; public class ApiModelParser { public Map getResponseBodyModels(Method method) { - Map documentationSchemaMap = new HashMap(); - if(method.getAnnotation(ResponseBody.class) != null) { - Class returnType = method.getReturnType(); - SwaggerSchemaConverter parser = new SwaggerSchemaConverter(); - String schemaName; - if(returnType.isArray()) { - //TODO - possibly reinvestigate what we should do in the case of an array - //parser = new ApiModelParser(returnType.getComponentType()); - schemaName = returnType.getComponentType().getSimpleName(); - } else { - schemaName = returnType.getSimpleName(); - } - Option model = parser.read(returnType); - if(model.nonEmpty()) { - documentationSchemaMap.put(schemaName, model.get()); - } - } - - return documentationSchemaMap; - } - - public Map getParameterModels(Method method) { - - Map documentationSchemaMap = new HashMap(); + Map models = new HashMap(); + if (method.getAnnotation(ResponseBody.class) != null) { + Type type = method.getGenericReturnType(); - List annotatedParameters = AnnotationUtils.getAnnotatedParameters(method); - for (AnnotatedParameter annotatedParameter : annotatedParameters) { - Class parameterType = annotatedParameter.getParameterType(); - SwaggerSchemaConverter parser = new SwaggerSchemaConverter(); - Option model = parser.read(parameterType); - if(model.nonEmpty()) { - documentationSchemaMap.put(parameterType.getSimpleName(), model.get()); - } + ApiUtils.addModels(type, models); } - return documentationSchemaMap; + return models; } } diff --git a/src/main/java/com/knappsack/swagger4springweb/parser/ApiOperationParser.java b/src/main/java/com/knappsack/swagger4springweb/parser/ApiOperationParser.java index 9cc6411..c1c5c25 100644 --- a/src/main/java/com/knappsack/swagger4springweb/parser/ApiOperationParser.java +++ b/src/main/java/com/knappsack/swagger4springweb/parser/ApiOperationParser.java @@ -4,25 +4,33 @@ import com.wordnik.swagger.annotations.ApiOperation; import com.wordnik.swagger.annotations.ApiResponse; import com.wordnik.swagger.annotations.ApiResponses; +import com.wordnik.swagger.converter.ModelConverters; +import com.wordnik.swagger.model.Model; import com.wordnik.swagger.model.Operation; import com.wordnik.swagger.model.Parameter; import com.wordnik.swagger.model.ResponseMessage; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import scala.Option; import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import static java.lang.String.format; + public class ApiOperationParser { private String resourcePath; private List ignorableAnnotations; private boolean ignoreUnusedPathVariables; - public ApiOperationParser(String resourcePath, List ignorableAnnotations, boolean ignoreUnusedPathVariables) { + public ApiOperationParser(String resourcePath, List ignorableAnnotations, + boolean ignoreUnusedPathVariables) { this.ignorableAnnotations = ignorableAnnotations; this.ignoreUnusedPathVariables = ignoreUnusedPathVariables; this.resourcePath = resourcePath; @@ -31,108 +39,106 @@ public ApiOperationParser(String resourcePath, List ignorableAnnotations public Operation getDocumentationOperation(Method method) { DocumentationOperation documentationOperation = new DocumentationOperation(); - documentationOperation.setName(method.getName()); documentationOperation.setNickname(method.getName());// method name - documentationOperation.setResponseTypeInternal(method.getReturnType().getName()); - String responseClass; - Class returnType = method.getReturnType(); - if(returnType.isArray()) { - responseClass = returnType.getComponentType().getSimpleName(); - } else { - responseClass = method.getReturnType().getSimpleName(); + + Type returnType = method.getGenericReturnType(); + if (returnType instanceof ParameterizedType) { + final ParameterizedType parameterizedType = (ParameterizedType) returnType; + + if (parameterizedType.getActualTypeArguments().length == 1) { + final Type type = parameterizedType.getActualTypeArguments()[0]; + if (type instanceof ParameterizedType) { + documentationOperation.setResponseClass((Class) ((ParameterizedType) type).getRawType()); + } else { + documentationOperation.setResponseClass((Class) type); + } + documentationOperation + .setResponseContainer(((Class) parameterizedType.getRawType())); + } else { + // TODO what to do here? + // not supporting generic containing other generic + } } - documentationOperation.setResponseClass(responseClass); - String httpMethod = ""; - RequestMapping methodRequestMapping = method - .getAnnotation(RequestMapping.class); - if (httpMethod.isEmpty()) { - for (RequestMethod requestMethod : methodRequestMapping.method()) { - httpMethod += requestMethod.name() + " "; + if (StringUtils.isEmpty(documentationOperation.getResponseClass())) { + Class clazz = method.getReturnType(); + if (clazz.isArray()) { + documentationOperation.setResponseClass(clazz.getComponentType()); + } else { + documentationOperation.setResponseClass(clazz); } } - documentationOperation.getConsumes().addAll(Arrays.asList(methodRequestMapping.consumes())); + + String httpMethod = ""; + RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class); + for (RequestMethod requestMethod : methodRequestMapping.method()) { + httpMethod += requestMethod.name() + " "; + } documentationOperation.setHttpMethod(httpMethod.trim()); - documentationOperation.getProduces().addAll(Arrays.asList(methodRequestMapping.produces())); + documentationOperation.addConsumes(Arrays.asList(methodRequestMapping.consumes())); + documentationOperation.addProduces(Arrays.asList(methodRequestMapping.produces())); // get ApiOperation information ApiOperation apiOperation = method.getAnnotation(ApiOperation.class); if (apiOperation != null) { - if (!apiOperation.httpMethod().isEmpty()) { - httpMethod = apiOperation.httpMethod(); - } - if (!(apiOperation.response() == null)) { - documentationOperation.setResponseClass(apiOperation.response().getName()); - } + documentationOperation.setHttpMethod(apiOperation.httpMethod()); + documentationOperation.setResponseClass(apiOperation.response()); + documentationOperation.setResponseContainer(apiOperation.responseContainer()); + documentationOperation.addProduces(apiOperation.produces()); + documentationOperation.addConsumes(apiOperation.consumes()); documentationOperation.setSummary(apiOperation.value()); documentationOperation.setNotes(apiOperation.notes()); documentationOperation.setPosition(apiOperation.position()); - documentationOperation.getProduces().add(apiOperation.produces()); - documentationOperation.getConsumes().add(apiOperation.consumes()); - documentationOperation.getProtocols().add(apiOperation.protocols()); - documentationOperation.getAuthorizations().add(apiOperation.authorizations()); - documentationOperation.setHttpMethod(httpMethod); + documentationOperation.addProtocols(apiOperation.protocols()); + documentationOperation.addAuthorizations(apiOperation.authorizations()); } - ApiResponse apiError = method.getAnnotation(ApiResponse.class); - if (apiError != null) { - addError(documentationOperation, apiError); + ApiResponse apiResponse = method.getAnnotation(ApiResponse.class); + if (apiResponse != null) { + addResponse(documentationOperation, apiResponse); } - ApiResponses apiErrors = method.getAnnotation(ApiResponses.class); - if (apiErrors != null) { - ApiResponse[] errors = apiErrors.value(); - for (ApiResponse error : errors) { - addError(documentationOperation, error); + ApiResponses apiResponses = method.getAnnotation(ApiResponses.class); + if (apiResponses != null) { + ApiResponse[] responses = apiResponses.value(); + for (ApiResponse response : responses) { + addResponse(documentationOperation, response); } } ApiParameterParser apiParameterParser = new ApiParameterParser(ignorableAnnotations); - List documentationParameters = apiParameterParser - .getApiParameters(method); + List documentationParameters = apiParameterParser.getApiParameters(method); documentationOperation.setParameters(documentationParameters); addUnusedPathVariables(documentationOperation, methodRequestMapping.value()); - - return new Operation(documentationOperation.getHttpMethod(), - documentationOperation.getSummary(), - documentationOperation.getNotes(), - documentationOperation.getResponseClass(), - documentationOperation.getNickname(), - documentationOperation.getPosition(), - JavaToScalaUtil.toScalaList(documentationOperation.getProduces()), - JavaToScalaUtil.toScalaList(documentationOperation.getConsumes()), - JavaToScalaUtil.toScalaList(documentationOperation.getProtocols()), - JavaToScalaUtil.toScalaList(documentationOperation.getAuthorizations()), - JavaToScalaUtil.toScalaList(documentationOperation.getParameters()) , - JavaToScalaUtil.toScalaList(documentationOperation.getResponseMessages()), - null); + return documentationOperation.toScalaOperation(); } - private void addError(DocumentationOperation documentationOperation, ApiResponse apiError) { - Option responseOption = Option.apply(apiError.response().getName()); - ResponseMessage responseMessage = new ResponseMessage(apiError.code(), apiError.message(),responseOption); - documentationOperation.getResponseMessages().add(responseMessage); + private void addResponse(DocumentationOperation documentationOperation, ApiResponse apiResponse) { + Option responseOption = Option.apply(apiResponse.response().getName()); + ResponseMessage responseMessage = new ResponseMessage(apiResponse.code(), apiResponse.message(), + responseOption); + documentationOperation.addResponseMessage(responseMessage); } private void addUnusedPathVariables(DocumentationOperation documentationOperation, String[] methodPath) { - if(ignoreUnusedPathVariables){ - return; + if (ignoreUnusedPathVariables) { + return; } - for(Parameter documentationParameter : new ApiPathParser().getPathParameters(resourcePath, methodPath)){ - if(!isParameterPresented(documentationOperation, documentationParameter.name())){ - documentationOperation.getParameters().add(documentationParameter); + for (Parameter documentationParameter : new ApiPathParser().getPathParameters(resourcePath, methodPath)) { + if (!isParameterPresented(documentationOperation, documentationParameter.name())) { + documentationOperation.addParameter(documentationParameter); } } } - private boolean isParameterPresented(DocumentationOperation documentationOperation, String parameter){ - if(parameter == null || documentationOperation.getParameters() == null){ + private boolean isParameterPresented(DocumentationOperation documentationOperation, String parameter) { + if (documentationOperation.getParameters().isEmpty()) { return false; } - for(Parameter documentationParameter : documentationOperation.getParameters()){ - if(parameter.equals(documentationParameter.name())){ + for (Parameter documentationParameter : documentationOperation.getParameters()) { + if (parameter.equals(documentationParameter.name())) { return true; } } @@ -141,9 +147,8 @@ private boolean isParameterPresented(DocumentationOperation documentationOperati //This class is used as a temporary solution to create a Swagger Operation object, since the Operation is immutable class DocumentationOperation { - private String name; + private String nickname; - private String responseTypeInternal; private String responseClass; private String summary; private String notes; @@ -156,116 +161,129 @@ class DocumentationOperation { private List protocols = new ArrayList(); private List authorizations = new ArrayList(); - String getName() { - return name; - } - - void setName(String name) { - this.name = name; - } - - String getNickname() { - return nickname; + Operation toScalaOperation() { + return new Operation(httpMethod, + summary, + notes, + responseClass, + nickname, + position, + JavaToScalaUtil.toScalaList(produces), + JavaToScalaUtil.toScalaList(consumes), + JavaToScalaUtil.toScalaList(protocols), + JavaToScalaUtil.toScalaList(authorizations), + JavaToScalaUtil.toScalaList(parameters), + JavaToScalaUtil.toScalaList(responseMessages), + null); } void setNickname(String nickname) { this.nickname = nickname; } - String getResponseTypeInternal() { - return responseTypeInternal; - } - - void setResponseTypeInternal(String responseTypeInternal) { - this.responseTypeInternal = responseTypeInternal; - } - - String getResponseClass() { - return responseClass; - } - - void setResponseClass(String responseClass) { - this.responseClass = responseClass; - } + void setResponseClass(Class responseClass) { + if (responseClass == null || responseClass == Void.class) { + return; + } - String getSummary() { - return summary; + Option model = ModelConverters.read(responseClass); + if (model.nonEmpty()) { + this.responseClass = model.get().name(); + } else { + this.responseClass = responseClass.getSimpleName(); + } } void setSummary(String summary) { this.summary = summary; } - String getNotes() { - return notes; - } - void setNotes(String notes) { this.notes = notes; } - String getHttpMethod() { - return httpMethod; - } - void setHttpMethod(String httpMethod) { + if (StringUtils.isEmpty(httpMethod)) { + return; + } this.httpMethod = httpMethod; } - List getParameters() { - return parameters; - } - void setParameters(List parameters) { this.parameters = parameters; } - List getResponseMessages() { - return responseMessages; + void setPosition(int position) { + this.position = position; } - void setResponseMessages(List responseMessages) { - this.responseMessages = responseMessages; + void addConsumes(final List consumes) { + this.consumes.addAll(consumes); } - int getPosition() { - return position; + void addProduces(final List produces) { + this.produces.addAll(produces); } - void setPosition(int position) { - this.position = position; + public void addResponseMessage(final ResponseMessage responseMessage) { + this.responseMessages.add(responseMessage); + } + + public List getParameters() { + return parameters; } - List getProduces() { - return produces; + public void addParameter(final Parameter parameter) { + this.parameters.add(parameter); } - void setProduces(List produces) { - this.produces = produces; + public void addAuthorizations(final String authorizations) { + if (StringUtils.isEmpty(authorizations)) { + return; + } + this.authorizations.add(authorizations); } - List getConsumes() { - return consumes; + void addProtocols(final String protocols) { + if (StringUtils.isEmpty(protocols)) { + return; + } + this.protocols.add(protocols); } - void setConsumes(List consumes) { - this.consumes = consumes; + public void addProduces(final String produces) { + if (StringUtils.isEmpty(produces)) { + return; + } + this.produces.add(produces); } - List getProtocols() { - return protocols; + public void addConsumes(final String consumes) { + if (StringUtils.isEmpty(consumes)) { + return; + } + this.consumes.add(consumes); } - void setProtocols(List protocols) { - this.protocols = protocols; + public void setResponseContainer(final String container) { + if (StringUtils.isEmpty(container)) { + return; + } + this.responseClass = format("%s[%s]", container, responseClass); } - List getAuthorizations() { - return authorizations; + public void setResponseContainer(final Class type) { + Option model = ModelConverters.read(type); + if (model.nonEmpty()) { + setResponseContainer(model.get().name()); + } else { + setResponseContainer(type.getSimpleName()); + } } - void setAuthorizations(List authorizations) { - this.authorizations = authorizations; + public String getResponseClass() { + return responseClass; } + } } diff --git a/src/main/java/com/knappsack/swagger4springweb/parser/ApiParserImpl.java b/src/main/java/com/knappsack/swagger4springweb/parser/ApiParserImpl.java index f07d663..640ab01 100644 --- a/src/main/java/com/knappsack/swagger4springweb/parser/ApiParserImpl.java +++ b/src/main/java/com/knappsack/swagger4springweb/parser/ApiParserImpl.java @@ -3,6 +3,7 @@ import com.knappsack.swagger4springweb.annotation.ApiExclude; import com.knappsack.swagger4springweb.controller.ApiDocumentationController; import com.knappsack.swagger4springweb.util.AnnotationUtils; +import com.knappsack.swagger4springweb.util.ApiUtils; import com.knappsack.swagger4springweb.util.JavaToScalaUtil; import com.knappsack.swagger4springweb.util.ScalaToJavaUtil; import com.wordnik.swagger.annotations.Api; @@ -25,6 +26,7 @@ import static org.reflections.ReflectionUtils.withAnnotation; public class ApiParserImpl implements ApiParser { + private static final String swaggerVersion = com.wordnik.swagger.core.SwaggerSpec.version(); private List controllerPackages = new ArrayList(); @@ -39,7 +41,8 @@ public class ApiParserImpl implements ApiParser { private final Map apiListingMap = new HashMap(); - public ApiParserImpl(ApiInfo apiInfo, List baseControllerPackage, List baseModelPackage, String basePath, String servletPath, + public ApiParserImpl(ApiInfo apiInfo, List baseControllerPackage, List baseModelPackage, + String basePath, String servletPath, String apiVersion, List ignorableAnnotations, boolean ignoreUnusedPathVariables) { this.controllerPackages = baseControllerPackage; this.modelPackages = baseModelPackage; @@ -51,7 +54,7 @@ public ApiParserImpl(ApiInfo apiInfo, List baseControllerPackage, List apiListingMap) if (!key.startsWith("/")) { docPath = docPath + "/"; } - ApiListingReference apiListingReference = new ApiListingReference(docPath + key, apiListing.description(), count); + ApiListingReference apiListingReference = new ApiListingReference(docPath + key, apiListing.description(), + count); apiListingReferences.add(apiListingReference); count++; } - return new ResourceListing(apiVersion, swaggerVersion, JavaToScalaUtil.toScalaList(apiListingReferences), null, swaggerConfig.info()); + return new ResourceListing(apiVersion, swaggerVersion, JavaToScalaUtil.toScalaList(apiListingReferences), null, + swaggerConfig.info()); } public Map createApiListings() { @@ -100,14 +105,15 @@ private Map processControllers(Set> controllerClass continue; } - Set requestMappingMethods = Reflections.getAllMethods(controllerClass, withAnnotation(RequestMapping.class)); + Set requestMappingMethods = Reflections + .getAllMethods(controllerClass, withAnnotation(RequestMapping.class)); ApiListing apiListing = processControllerApi(controllerClass); String description = ""; Api controllerApi = controllerClass.getAnnotation(Api.class); if (controllerApi != null) { description = controllerApi.description(); } else { - if(apiListing.apis() == null) { + if (apiListing.apis() == null) { apiListing = processMethods(requestMappingMethods, apiListing, description); //Loop over operations 'methods' //processMethods(requestMappingMethods, apiListing, description); @@ -136,7 +142,8 @@ private ApiListing processControllerApi(Class controllerClass) { if (controllerApi == null || resourcePath.isEmpty()) { RequestMapping controllerRequestMapping = controllerClass.getAnnotation(RequestMapping.class); - if (controllerRequestMapping != null && controllerRequestMapping.value() != null && controllerRequestMapping.value().length > 0) { + if (controllerRequestMapping != null && controllerRequestMapping.value() != null && + controllerRequestMapping.value().length > 0) { resourcePath = controllerRequestMapping.value()[0]; } else { resourcePath = controllerClass.getName(); @@ -146,26 +153,27 @@ private ApiListing processControllerApi(Class controllerClass) { SpringApiReader reader = new SpringApiReader(); Option apiListingOption = reader.read(resourcePath, controllerClass, swaggerConfig); ApiListing apiListing = null; - if(apiListingOption.nonEmpty()) { - apiListing = reader.read(resourcePath, controllerClass, swaggerConfig).get(); + if (apiListingOption.nonEmpty()) { + apiListing = apiListingOption.get(); } //Allow for multiple controllers having the same resource path. ApiListing existingApiListing = apiListingMap.get(resourcePath); - if (existingApiListing != null){ - return existingApiListing; + if (existingApiListing != null) { + return existingApiListing; } - if(apiListing != null) { + if (apiListing != null) { return apiListing; } - return new ApiListing(apiVersion, swaggerVersion, basePath, resourcePath, null, null, null, null, null, null, null, 0); + return new ApiListing(apiVersion, swaggerVersion, basePath, resourcePath, null, null, null, null, null, null, + null, 0); } private ApiListing processMethods(Collection methods, ApiListing apiListing, String description) { Map endPointMap = new HashMap(); - + populateApiDescriptionMapForApiListing(apiListing, endPointMap); for (Method method : methods) { @@ -175,10 +183,10 @@ private ApiListing processMethods(Collection methods, ApiListing apiList String requestMappingValue = AnnotationUtils.getMethodRequestMappingValue(method); ApiDescriptionParser documentationEndPointParser = new ApiDescriptionParser(); - ApiDescription apiDescription = documentationEndPointParser.getApiDescription(method, description, apiListing.resourcePath()); + ApiDescription apiDescription = documentationEndPointParser + .getApiDescription(method, description, apiListing.resourcePath()); if (!endPointMap.containsKey(requestMappingValue)) { endPointMap.put(requestMappingValue, apiDescription); -// documentation.apis().add(documentationEndPoint); } } @@ -190,13 +198,13 @@ private ApiListing processMethods(Collection methods, ApiListing apiList String value = AnnotationUtils.getMethodRequestMappingValue(method); List operations = operationMap.get(value); - if(operations == null) { + if (operations == null) { operations = new ArrayList(); operationMap.put(value, operations); } -// ApiDescription documentationEndPoint = endPointMap.get(value); - ApiOperationParser apiOperationParser = new ApiOperationParser(apiListing.resourcePath(), ignorableAnnotations, ignoreUnusedPathVariables); + ApiOperationParser apiOperationParser = new ApiOperationParser(apiListing.resourcePath(), + ignorableAnnotations, ignoreUnusedPathVariables); Operation operation = apiOperationParser.getDocumentationOperation(method); operations.add(operation); } @@ -204,43 +212,34 @@ private ApiListing processMethods(Collection methods, ApiListing apiList List newApiDescriptions = new ArrayList(); for (String key : endPointMap.keySet()) { ApiDescription apiDescription = endPointMap.get(key); - ApiDescription newApiDescription = new ApiDescription(apiDescription.path(), apiDescription.description(), JavaToScalaUtil.toScalaList(operationMap.get(key))); + ApiDescription newApiDescription = new ApiDescription(apiDescription.path(), apiDescription.description(), + JavaToScalaUtil.toScalaList(operationMap.get(key))); newApiDescriptions.add(newApiDescription); } - Map modelMap = new HashMap(); for (Method method : methods) { ApiModelParser apiModelParser = new ApiModelParser(); - modelMap.putAll(apiModelParser.getResponseBodyModels(method)); -// for (String key : documentationSchemaMap.keySet()) { -// documentation.models().add(key, documentationSchemaMap.get(key)); -// } -// -// Map> parameterDocumentationSchemaMap = apiModelParser.getParameterDocumentationSchema(method); -// for (String key : parameterDocumentationSchemaMap.keySet()) { -// documentation.models().add(key, parameterDocumentationSchemaMap.get(key)); -// } + apiListingModels.putAll(apiModelParser.getResponseBodyModels(method)); } -// Map apiListingModels = createApiListingModels(); + Option> modelOptions = Option + .apply(JavaToScalaUtil.toScalaImmutableMap(apiListingModels)); -// Option.>empty(); -// ScalaToJavaUtil.toScalaImmutableMap(documentationSchemaMap); - Option> modelOptions = Option.apply(JavaToScalaUtil.toScalaImmutableMap(apiListingModels)); - - return new ApiListing(apiListing.apiVersion(), apiListing.swaggerVersion(), apiListing.basePath(), apiListing.resourcePath(), - apiListing.produces(), apiListing.consumes(), apiListing.protocols(), apiListing.authorizations(), JavaToScalaUtil.toScalaList(newApiDescriptions), modelOptions, + return new ApiListing(apiListing.apiVersion(), apiListing.swaggerVersion(), apiListing.basePath(), + apiListing.resourcePath(), apiListing.produces(), apiListing.consumes(), apiListing.protocols(), + apiListing.authorizations(), JavaToScalaUtil.toScalaList(newApiDescriptions), modelOptions, apiListing.description(), apiListing.position()); } - private void populateApiDescriptionMapForApiListing(ApiListing apiListing, Map apiDescriptionMap){ - if (apiListing.apis() != null){ + private void populateApiDescriptionMapForApiListing(ApiListing apiListing, + Map apiDescriptionMap) { + if (apiListing.apis() != null) { - List apiDescriptions = ScalaToJavaUtil.toJavaList(apiListing.apis()); - for (ApiDescription apiDescription : apiDescriptions){ - apiDescriptionMap.put(apiDescription.path(), apiDescription); - } - } + List apiDescriptions = ScalaToJavaUtil.toJavaList(apiListing.apis()); + for (ApiDescription apiDescription : apiDescriptions) { + apiDescriptionMap.put(apiDescription.path(), apiDescription); + } + } } private void createApiListingModels() { @@ -253,28 +252,7 @@ private void createApiListingModels() { .setScanners(new SubTypesScanner(false), new ResourcesScanner())); Set> allModelClasses = reflections.getSubTypesOf(Object.class); for (Class clazz : allModelClasses) { - Model model = null; -// ApiModelParser parser; - String schemaName; - if (clazz.isArray()) { -// parser = new ApiModelParser(clazz.getComponentType()); - schemaName = clazz.getComponentType().getSimpleName(); - Option modelOption = ModelConverters.read(clazz.getComponentType()); - if(modelOption.nonEmpty()) { - model = modelOption.get(); - } - } else { -// parser = new ApiModelParser(clazz); - schemaName = clazz.getSimpleName(); - Option modelOption = ModelConverters.read(clazz); - if(modelOption.nonEmpty()) { - model = modelOption.get(); - } - } - if(model != null) { - modelMap.put(schemaName, model); - } -// documentation.addModel(schemaName, parser.parse().toDocumentationSchema()); + ApiUtils.addModels(clazz, modelMap); } } apiListingModels = modelMap; diff --git a/src/main/java/com/knappsack/swagger4springweb/util/ApiUtils.java b/src/main/java/com/knappsack/swagger4springweb/util/ApiUtils.java index d3b504c..6a9c4b4 100644 --- a/src/main/java/com/knappsack/swagger4springweb/util/ApiUtils.java +++ b/src/main/java/com/knappsack/swagger4springweb/util/ApiUtils.java @@ -1,10 +1,15 @@ package com.knappsack.swagger4springweb.util; +import com.wordnik.swagger.converter.ModelConverters; +import com.wordnik.swagger.model.Model; import org.springframework.web.bind.annotation.ValueConstants; import org.springframework.web.multipart.MultipartFile; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.Collection; import java.util.Date; +import java.util.Map; /** * Author: andrey.antonov @@ -14,7 +19,7 @@ public class ApiUtils { public static String getSwaggerTypeFor(Class parameterType) { Class type = parameterType; - if(parameterType.isArray()) { + if (parameterType.isArray()) { type = type.getComponentType(); } // swagger types are @@ -30,21 +35,21 @@ public static String getSwaggerTypeFor(Class parameterType) { return "string"; } else if (Boolean.class.isAssignableFrom(type)) { return "boolean"; - } else if(Byte.class.isAssignableFrom(type)) { + } else if (Byte.class.isAssignableFrom(type)) { return "byte"; - } else if(Long.class.isAssignableFrom(type)) { + } else if (Long.class.isAssignableFrom(type)) { return "int64"; - } else if(Integer.class.isAssignableFrom(type)) { + } else if (Integer.class.isAssignableFrom(type)) { return "int32"; - } else if(Float.class.isAssignableFrom(type)) { + } else if (Float.class.isAssignableFrom(type)) { return "float"; - } else if(MultipartFile.class.isAssignableFrom(type)) { + } else if (MultipartFile.class.isAssignableFrom(type)) { return "file"; } else if (Number.class.isAssignableFrom(type)) { return "double"; - } else if(Double.class.isAssignableFrom(type)) { + } else if (Double.class.isAssignableFrom(type)) { return "double"; - } else if(Date.class.isAssignableFrom(type)) { + } else if (Date.class.isAssignableFrom(type)) { return "date"; } // others @@ -58,4 +63,32 @@ public static boolean isSet(String value) { public static boolean isAllowMultiple(Class parameterType) { return parameterType != null && (parameterType.isArray() || Collection.class.isAssignableFrom(parameterType)); } + + static boolean isIgnorableModel(String name) { + return name.equalsIgnoreCase("map") || name.equalsIgnoreCase("list") || name.equalsIgnoreCase("string"); + } + + public static void addModels(final Class clazz, final Map models) { + scala.collection.immutable.List modelOption = ModelConverters.readAll(clazz); + scala.collection.Iterator iter = modelOption.iterator(); + while (iter.hasNext()) { + Model model = iter.next(); + if (!isIgnorableModel(model.name())) { + models.put(model.name(), model); + } + } + } + + public static void addModels(final Type type, final Map models) { + if (type instanceof ParameterizedType) { + // Adding both part of generic type + final ParameterizedType parameterizedType = (ParameterizedType) type; + addModels(parameterizedType.getRawType(), models); + for (Type t : parameterizedType.getActualTypeArguments()) { + addModels(t, models); + } + } else if (type instanceof Class) { + addModels((Class) type, models); + } + } }