Skip to content

Commit

Permalink
Merge pull request #15 from dayman/master
Browse files Browse the repository at this point in the history
Documentation of unused (directly in method) path variables
  • Loading branch information
Will Kennedy committed Jul 11, 2013
2 parents e47cd33 + 705b69c commit 7dd2733
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 79 deletions.
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

0 comments on commit 7dd2733

Please sign in to comment.