Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation of unused (directly in method) path variables #15

Merged
merged 3 commits into from
Jul 11, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<org.wordnik-swagger-version>1.2.4</org.wordnik-swagger-version>
<org.slf4j-version>1.6.4</org.slf4j-version>
<org.logback-version>1.0.1</org.logback-version>
<java.version>1.5</java.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -143,6 +144,14 @@

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ public class ApiDocumentationController {
private List<String> additionalModelPackages = new ArrayList<String>();
private String basePath = "";
private String apiVersion = "v1";
private Documentation resourceList;
private Map<String, Documentation> documentation;
private List<String> ignorableAnnotations = new ArrayList<String>();

private boolean ignoreUnusedPathVariables = true;
private Documentation resourceList;

@RequestMapping(value = "/resourceList", method = RequestMethod.GET, produces = "application/json")
public
Expand All @@ -46,11 +46,13 @@ Documentation getDocumentation(HttpServletRequest request) {
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
//trim the operation request mapping from the desired value
handlerMappingPath = handlerMappingPath.substring(handlerMappingPath.lastIndexOf("/doc") + 4, handlerMappingPath.length());
if (getDocs(request) == null) {

Map<String, Documentation> docs = getDocs(request);
if (docs == null) {
return new Documentation();
}

return getDocs(request).get(handlerMappingPath);
return docs.get(handlerMappingPath);
}

@SuppressWarnings("unused")
Expand Down Expand Up @@ -139,8 +141,9 @@ private Map<String, Documentation> getDocs(HttpServletRequest request) {
if(request != null) {
servletPath = request.getServletPath();
}
ApiParser apiParser = new ApiParserImpl(getControllerPackages(), getModelPackages(), getBasePath(), servletPath, apiVersion, ignorableAnnotations);
this.documentation = apiParser.createDocuments();
ApiParser apiParser = new ApiParserImpl(getControllerPackages(), getModelPackages(), getBasePath(),
servletPath, apiVersion, ignorableAnnotations, ignoreUnusedPathVariables);
documentation = apiParser.createDocuments();
}
return documentation;
}
Expand All @@ -152,8 +155,9 @@ private Documentation getResourceList(HttpServletRequest request) {
servletPath = request.getServletPath();
servletPath = servletPath.replace("/resourceList", "");
}
ApiParser apiParser = new ApiParserImpl(getControllerPackages(), getModelPackages(), getBasePath(), servletPath, apiVersion, ignorableAnnotations);
this.resourceList = apiParser.getResourceListing(getDocs(request));
ApiParser apiParser = new ApiParserImpl(getControllerPackages(), getModelPackages(), getBasePath(),
servletPath, apiVersion, ignorableAnnotations, ignoreUnusedPathVariables);
resourceList = apiParser.getResourceListing(getDocs(request));
}
return resourceList;
}
Expand Down Expand Up @@ -196,4 +200,12 @@ public List<String> getIgnorableAnnotations() {
public void setIgnorableAnnotations(List<String> ignorableAnnotations) {
this.ignorableAnnotations = ignorableAnnotations;
}

public boolean isIgnoreUnusedPathVariables() {
return ignoreUnusedPathVariables;
}

public void setIgnoreUnusedPathVariables(final boolean ignoreUnusedPathVariables) {
this.ignoreUnusedPathVariables = ignoreUnusedPathVariables;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,16 @@ public class ApiParserImpl implements ApiParser {
private String servletPath = "/api";
private String apiVersion = "v1";
private List<String> ignorableAnnotations;
private boolean ignoreUnusedPathVariables;

private final Map<String, Documentation> documents = new HashMap<String, Documentation>();

public ApiParserImpl(List<String> baseControllerPackage, List<String> baseModelPackage, String basePath, String servletPath, String apiVersion, List<String> ignorableAnnotations) {
public ApiParserImpl(List<String> baseControllerPackage, List<String> baseModelPackage, String basePath, String servletPath,
String apiVersion, List<String> ignorableAnnotations, boolean ignoreUnusedPathVariables) {
this.controllerPackages = baseControllerPackage;
this.modelPackages = baseModelPackage;
this.ignorableAnnotations = ignorableAnnotations;
this.ignoreUnusedPathVariables = ignoreUnusedPathVariables;
this.basePath = basePath;
this.apiVersion = apiVersion;
if (servletPath != null && !servletPath.isEmpty()) {
Expand Down Expand Up @@ -117,8 +120,9 @@ private Documentation processControllerDocumentation(Class<?> controllerClass) {
}

//Allow for multiple controllers having the same resource path.
if (documents.containsKey(resourcePath)){
return documents.get(resourcePath);
Documentation documentation = documents.get(resourcePath);
if (documentation != null){
return documentation;
}

return new Documentation(apiVersion, swaggerVersion, basePath, resourcePath);
Expand All @@ -143,7 +147,7 @@ private void processMethods(Set<Method> methods, Documentation documentation, St
String value = AnnotationUtils.getMethodRequestMappingValue(method);
DocumentationEndPoint documentationEndPoint = endPointMap.get(value);

DocumentationOperationParser documentationOperationParser = new DocumentationOperationParser(ignorableAnnotations);
DocumentationOperationParser documentationOperationParser = new DocumentationOperationParser(documentation.resourcePath(), ignorableAnnotations, ignoreUnusedPathVariables);
DocumentationOperation documentationOperation = documentationOperationParser.getDocumentationOperation(method);
documentationEndPoint.addOperation(documentationOperation);

Expand All @@ -159,7 +163,7 @@ private void processMethods(Set<Method> methods, Documentation documentation, St
}
}
}

private void populateEndpointMapForDocumentation(Documentation documentation, Map<String, DocumentationEndPoint> endPointMap){
if (documentation.getApis() != null){
for (DocumentationEndPoint endpoint : documentation.getApis()){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@
import org.springframework.web.bind.annotation.RequestMethod;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class DocumentationOperationParser {

private String resourcePath;
private List<String> ignorableAnnotations;
private boolean ignoreUnusedPathVariables;

public DocumentationOperationParser() {
ignorableAnnotations = new ArrayList<String>();
}

public DocumentationOperationParser(List<String> ignorableAnnotations) {
public DocumentationOperationParser(String resourcePath, List<String> ignorableAnnotations, boolean ignoreUnusedPathVariables) {
this.ignorableAnnotations = ignorableAnnotations;
this.ignoreUnusedPathVariables = ignoreUnusedPathVariables;
this.resourcePath = resourcePath;
}

public DocumentationOperation getDocumentationOperation(Method method) {
Expand Down Expand Up @@ -72,15 +71,39 @@ public DocumentationOperation getDocumentationOperation(Method method) {
List<DocumentationParameter> documentationParameters = documentationParameterParser
.getDocumentationParams(method);
documentationOperation.setParameters(documentationParameters);
addUnusedPathVariables(documentationOperation, methodRequestMapping.value());

return documentationOperation;
}

private void addError(DocumentationOperation documentationOperation,
ApiError apiError) {
private void addError(DocumentationOperation documentationOperation, ApiError apiError) {
DocumentationError documentationError = new DocumentationError();
documentationError.setCode(apiError.code());
documentationError.setReason(apiError.reason());
documentationOperation.addErrorResponse(documentationError);
}

private void addUnusedPathVariables(DocumentationOperation documentationOperation, String[] methodPath) {
if(ignoreUnusedPathVariables){
return;
}

for(DocumentationParameter documentationParameter : new DocumentationPathParser().getPathParameters(resourcePath, methodPath)){
if(!isParameterPresented(documentationOperation, documentationParameter.getName())){
documentationOperation.addParameter(documentationParameter);
}
}
}

private boolean isParameterPresented(DocumentationOperation documentationOperation, String parameter){
if(parameter == null || documentationOperation.getParameters() == null){
return false;
}
for(DocumentationParameter documentationParameter : documentationOperation.getParameters()){
if(parameter.equals(documentationParameter.getName())){
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@

import com.knappsack.swagger4springweb.model.AnnotatedParameter;
import com.knappsack.swagger4springweb.util.AnnotationUtils;
import com.knappsack.swagger4springweb.util.DocumentationUtils;
import com.wordnik.swagger.annotations.ApiParam;
import com.wordnik.swagger.core.ApiValues;
import com.wordnik.swagger.core.DocumentationAllowableListValues;
import com.wordnik.swagger.core.DocumentationParameter;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

public class DocumentationParameterParser {
Expand All @@ -38,10 +37,10 @@ public List<DocumentationParameter> getDocumentationParams(Method method) {
}
DocumentationParameter documentationParameter = new DocumentationParameter();
// default values from the Method
documentationParameter.setDataType(getSwaggerTypeFor(annotatedParameter.getParameterType()));
documentationParameter.setDataType(DocumentationUtils.getSwaggerTypeFor(annotatedParameter.getParameterType()));
documentationParameter.setName(annotatedParameter.getParameterName());
documentationParameter.setValueTypeInternal(annotatedParameter.getParameterType().getName());
documentationParameter.setAllowMultiple(isAllowMultiple(annotatedParameter.getParameterType()));
documentationParameter.setAllowMultiple(DocumentationUtils.isAllowMultiple(annotatedParameter.getParameterType()));
// apply default values from spring annotations first
for (Annotation annotation : annotatedParameter.getAnnotations()) {
addSpringParams(annotation, documentationParameter);
Expand All @@ -58,41 +57,6 @@ public List<DocumentationParameter> getDocumentationParams(Method method) {
return documentationParameters;
}

private String getSwaggerTypeFor(Class<?> parameterType) {
Class type = parameterType;
if(parameterType.isArray()) {
type = type.getComponentType();
}
// swagger types are
// byte
// boolean
// int
// long
// float
// double
// string
// Date
if (String.class.isAssignableFrom(type)) {
return "string";
} else if (Boolean.class.isAssignableFrom(type)) {
return "boolean";
} else if(Byte.class.isAssignableFrom(type)) {
return "byte";
} else if(Long.class.isAssignableFrom(type)) {
return "long";
} else if(Integer.class.isAssignableFrom(type)) {
return "int";
} else if(Float.class.isAssignableFrom(type)) {
return "float";
} else if(MultipartFile.class.isAssignableFrom(type)) {
return "file";
} else if (Number.class.isAssignableFrom(type)) {
return "double";
}
// others
return type.getSimpleName();
}

private void addSpringParams(Annotation annotation, DocumentationParameter documentationParameter) {
if (annotation instanceof RequestParam) {
addRequestParams((RequestParam) annotation, documentationParameter);
Expand All @@ -114,7 +78,7 @@ private void addRequestBody(DocumentationParameter documentationParameter) {
}

private void addPathVariable(PathVariable pathVariable, DocumentationParameter documentationParameter) {
if (isSet(pathVariable.value())) {
if (DocumentationUtils.isSet(pathVariable.value())) {
documentationParameter.setName(pathVariable.value());
}

Expand All @@ -124,10 +88,10 @@ private void addPathVariable(PathVariable pathVariable, DocumentationParameter d

private void addRequestParams(RequestParam requestParam,
DocumentationParameter documentationParameter) {
if (isSet(requestParam.value())) {
if (DocumentationUtils.isSet(requestParam.value())) {
documentationParameter.setName(requestParam.value());
}
if (isSet(requestParam.defaultValue())) {
if (DocumentationUtils.isSet(requestParam.defaultValue())) {
documentationParameter.setDefaultValue(requestParam.defaultValue());
}
documentationParameter.setRequired(requestParam.required());
Expand All @@ -138,16 +102,12 @@ private void addRequestParams(RequestParam requestParam,
}
}

private boolean isSet(String value) {
return value != null && !value.trim().isEmpty() && !ValueConstants.DEFAULT_NONE.equals(value);
}

private void addRequestHeader(RequestHeader requestHeader,
DocumentationParameter documentationParameter) {
if (isSet(requestHeader.value())) {
if (DocumentationUtils.isSet(requestHeader.value())) {
documentationParameter.setName(requestHeader.value());
}
if (isSet(requestHeader.defaultValue())) {
if (DocumentationUtils.isSet(requestHeader.defaultValue())) {
documentationParameter.setDefaultValue(requestHeader.defaultValue());
}
documentationParameter.setRequired(requestHeader.required());
Expand All @@ -156,21 +116,21 @@ private void addRequestHeader(RequestHeader requestHeader,

private void addApiParams(ApiParam apiParam,
DocumentationParameter documentationParameter) {
if (isSet(apiParam.allowableValues())) {
if (DocumentationUtils.isSet(apiParam.allowableValues())) {
// we use only one simple string
List<String> allowableValues = Arrays.asList(apiParam.allowableValues().split("\\s*,\\s*"));
documentationParameter.setAllowableValues(new DocumentationAllowableListValues(allowableValues));
}
documentationParameter.setAllowMultiple(apiParam.allowMultiple());

if (isSet(apiParam.defaultValue())) {
if (DocumentationUtils.isSet(apiParam.defaultValue())) {
documentationParameter.setDefaultValue(apiParam.defaultValue());
}
documentationParameter.setDescription(apiParam.value());
documentationParameter.setInternalDescription(apiParam
.internalDescription());
// overwrite default name
if (isSet(apiParam.name())) {
if (DocumentationUtils.isSet(apiParam.name())) {
documentationParameter.setName(apiParam.name());
}
// documentationParameter.setNotes(apiParam.);
Expand All @@ -182,10 +142,6 @@ private void addApiParams(ApiParam apiParam,
}
}

private boolean isAllowMultiple(Class parameterType) {
return parameterType != null && (parameterType.isArray() || Collection.class.isAssignableFrom(parameterType));
}

private boolean hasIgnorableAnnotations(List<Annotation> annotations) {
for(Annotation annotation : annotations) {
if(ignorableAnnotations.contains(annotation.annotationType().getCanonicalName())) {
Expand Down
Loading