diff --git a/.gitignore b/.gitignore index 0973671..090dfc0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ target *.iml *.ipr *.iws +.idea \ No newline at end of file diff --git a/pom.xml b/pom.xml index c472a5f..f5612c8 100644 --- a/pom.xml +++ b/pom.xml @@ -85,8 +85,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 diff --git a/src/main/java/org/versly/rest/wsdoc/AnnotationProcessor.java b/src/main/java/org/versly/rest/wsdoc/AnnotationProcessor.java index b8556c2..2ab18cc 100644 --- a/src/main/java/org/versly/rest/wsdoc/AnnotationProcessor.java +++ b/src/main/java/org/versly/rest/wsdoc/AnnotationProcessor.java @@ -17,15 +17,18 @@ package org.versly.rest.wsdoc; import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.versly.rest.wsdoc.impl.*; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; import javax.lang.model.element.*; import javax.lang.model.type.*; -import javax.lang.model.util.AbstractTypeVisitor6; +import javax.lang.model.util.AbstractTypeVisitor7; import javax.tools.Diagnostic; import javax.tools.FileObject; import javax.tools.StandardLocation; @@ -49,12 +52,13 @@ // - plural RequestMapping value support (i.e., two paths bound to one method) // - support for methods not marked with @RequestMapping whose class does have a @RequestMapping annotation @SupportedAnnotationTypes({"org.springframework.web.bind.annotation.RequestMapping", "javax.ws.rs.Path"}) +@SupportedSourceVersion(SourceVersion.RELEASE_7) public class AnnotationProcessor extends AbstractProcessor { private RestDocumentation _docs = new RestDocumentation(); private boolean _isComplete = false; - private Map _memoizedTypeMirrors = new HashMap(); - private Map _memoizedDeclaredTypes = new HashMap(); + private Map _memoizedTypeMirrors = new HashMap<>(); + private Map _memoizedDeclaredTypes = new HashMap<>(); @Override public boolean process(Set supportedAnnotations, RoundEnvironment roundEnvironment) { @@ -63,7 +67,7 @@ public boolean process(Set supportedAnnotations, RoundEnv if (_isComplete) return true; - Collection processedPackageNames = new LinkedHashSet(); + Collection processedPackageNames = new LinkedHashSet<>(); processElements(roundEnvironment, processedPackageNames, new SpringMVCRestImplementationSupport()); processElements(roundEnvironment, processedPackageNames, new JaxRSRestImplementationSupport()); @@ -168,7 +172,7 @@ private void scanForSpringMVCMultipart(ExecutableElement executableElement, Rest private void buildRequestBodies(ExecutableElement executableElement, RestDocumentation.Resource.Method doc, RestImplementationSupport implementationSupport) { - List requestBodies = new ArrayList(); + List requestBodies = new ArrayList<>(); for (VariableElement var : executableElement.getParameters()) { if (implementationSupport.isRequestBody(var)) requestBodies.add(var); @@ -283,8 +287,8 @@ private String[] getClassLevelUrlPaths(TypeElement cls, RestImplementationSuppor } } - private class TypeVisitorImpl extends AbstractTypeVisitor6 { - private Map _typeArguments = new HashMap(); + private class TypeVisitorImpl extends AbstractTypeVisitor7 { + private Map _typeArguments = new HashMap<>(); private Collection _typeRecursionDetector; private DeclaredType _type; @@ -319,7 +323,7 @@ private void loadTypeElements(DeclaredType type, List type @Override public JsonType visitPrimitive(PrimitiveType primitiveType, Void o) { - return jsonTypeFromTypeMirror(primitiveType, new HashSet(_typeRecursionDetector)); + return jsonTypeFromTypeMirror(primitiveType, new HashSet<>(_typeRecursionDetector)); } @Override @@ -371,7 +375,7 @@ public JsonType visitDeclared(DeclaredType declaredType, Void o) { } else { TypeElement element = (TypeElement) declaredType.asElement(); if (element.getKind() == ElementKind.ENUM) { - List enumConstants = new ArrayList(); + List enumConstants = new ArrayList<>(); for (Element e : element.getEnclosedElements()) { if (e.getKind() == ElementKind.ENUM_CONSTANT) { enumConstants.add(e.toString()); @@ -427,6 +431,13 @@ private void buildTypeContents(JsonObject o, TypeElement element) { return; } + JsonIgnoreProperties jsonIgnoreProperties = element.getAnnotation(JsonIgnoreProperties.class); + if (jsonIgnoreProperties != null) { + for (String ignoreProperty : jsonIgnoreProperties.value()) { + o.ignoreProperty(ignoreProperty); + } + } + if (element.getSuperclass().getKind() != TypeKind.NONE) { // an interface's superclass is TypeKind.NONE @@ -452,6 +463,11 @@ private void addFieldFromBeanMethod(JsonObject o, ExecutableElement executableEl String beanName = methodName.substring(trimLength + 1, methodName.length()); beanName = methodName.substring(trimLength, trimLength + 1).toLowerCase() + beanName; + // ignore this property if is listed as JsonIgnoreProperties + if (o.isIgnoringProperty(beanName)) { + return; + } + // replace variables with the current concrete manifestation if (type instanceof TypeVariable) { type = getDeclaredTypeForTypeVariable((TypeVariable) type); @@ -465,14 +481,14 @@ private void addFieldFromBeanMethod(JsonObject o, ExecutableElement executableEl o.addField(beanName, jsonType) .setCommentText(docComment); } else { - o.addField(beanName, jsonTypeFromTypeMirror(type, new HashSet(_typeRecursionDetector))) + o.addField(beanName, jsonTypeFromTypeMirror(type, new HashSet<>(_typeRecursionDetector))) .setCommentText(docComment); } } private JsonType recurseForJsonType(DeclaredType type) { // loop over the element's generic types, and build a concrete list from the owning context - List concreteTypes = new ArrayList(); + List concreteTypes = new ArrayList<>(); for (TypeMirror generic : type.getTypeArguments()) { if (generic instanceof DeclaredType) @@ -481,7 +497,7 @@ private JsonType recurseForJsonType(DeclaredType type) { concreteTypes.add(_typeArguments.get(((TypeVariable) generic).asElement().getSimpleName())); } _typeRecursionDetector.add(_type.toString()); - Collection types = new HashSet(_typeRecursionDetector); + Collection types = new HashSet<>(_typeRecursionDetector); return jsonTypeForDeclaredType(type, concreteTypes, types); } @@ -546,6 +562,11 @@ public JsonType visitNoType(NoType noType, Void o) { public JsonType visitUnknown(TypeMirror typeMirror, Void o) { throw new UnsupportedOperationException(typeMirror.toString()); } + + @Override + public JsonType visitUnion(UnionType unionType, Void aVoid) { + throw new UnsupportedOperationException(unionType.toString()); + } } public interface RestImplementationSupport { diff --git a/src/main/java/org/versly/rest/wsdoc/RestDocAssembler.java b/src/main/java/org/versly/rest/wsdoc/RestDocAssembler.java index 213f762..11870af 100644 --- a/src/main/java/org/versly/rest/wsdoc/RestDocAssembler.java +++ b/src/main/java/org/versly/rest/wsdoc/RestDocAssembler.java @@ -40,7 +40,7 @@ public static void main(String... args) Arguments arguments = new Arguments(); new JCommander(arguments, args); - List docs = new LinkedList(); + List docs = new LinkedList<>(); for (String input : arguments.inputs) { File inputFile = new File(input); if (inputFile.isDirectory()) { @@ -60,7 +60,7 @@ public static void main(String... args) } if (docs.size() > 0) { - List excludePatterns = new ArrayList(); + List excludePatterns = new ArrayList<>(); for (String pattern : arguments.excludes) excludePatterns.add(Pattern.compile(pattern)); new RestDocAssembler(arguments.outputFileName).writeDocumentation(docs, excludePatterns); @@ -76,7 +76,7 @@ void writeDocumentation(List docs, Iterable excludeP List filteredDocs; if (excludePatterns != null) { - filteredDocs = new ArrayList(); + filteredDocs = new ArrayList<>(); for (RestDocumentation doc : docs) filteredDocs.add(doc.filter(excludePatterns)); } else { @@ -89,7 +89,7 @@ void writeDocumentation(List docs, Iterable excludeP Writer out = null; try { Template template = conf.getTemplate("RestDocumentation.ftl"); - Map> root = new HashMap>(); + Map> root = new HashMap<>(); root.put("docs", filteredDocs); File file = getOutputFile(); out = new FileWriter(file); diff --git a/src/main/java/org/versly/rest/wsdoc/impl/JaxRSRestImplementationSupport.java b/src/main/java/org/versly/rest/wsdoc/impl/JaxRSRestImplementationSupport.java index 6eccab9..842694b 100644 --- a/src/main/java/org/versly/rest/wsdoc/impl/JaxRSRestImplementationSupport.java +++ b/src/main/java/org/versly/rest/wsdoc/impl/JaxRSRestImplementationSupport.java @@ -38,7 +38,7 @@ public String[] getRequestPaths(TypeElement cls) { @Override public String getRequestMethod(ExecutableElement executableElement, TypeElement contextClass) { - List methods = new ArrayList(); + List methods = new ArrayList<>(); gatherMethod(executableElement, methods, GET.class); gatherMethod(executableElement, methods, PUT.class); diff --git a/src/main/java/org/versly/rest/wsdoc/impl/JsonObject.java b/src/main/java/org/versly/rest/wsdoc/impl/JsonObject.java index a3b351a..e5e5ef5 100644 --- a/src/main/java/org/versly/rest/wsdoc/impl/JsonObject.java +++ b/src/main/java/org/versly/rest/wsdoc/impl/JsonObject.java @@ -21,10 +21,20 @@ public class JsonObject implements JsonType, Serializable { - private List _fields = new ArrayList(); + private transient Set ignoreProperties = new HashSet<>(); + + public void ignoreProperty(String name) { + ignoreProperties.add(name); + } + + public boolean isIgnoringProperty(String name) { + return ignoreProperties.contains(name); + } + + private List _fields = new ArrayList<>(); public JsonField addField(String fieldName, T value) { - JsonField field = new JsonField(fieldName, value); + JsonField field = new JsonField<>(fieldName, value); if (_fields.contains(field)) throw new IllegalStateException("field " + fieldName + " is already defined"); _fields.add(field); diff --git a/src/main/java/org/versly/rest/wsdoc/impl/JsonPrimitive.java b/src/main/java/org/versly/rest/wsdoc/impl/JsonPrimitive.java index 623189c..06740cf 100644 --- a/src/main/java/org/versly/rest/wsdoc/impl/JsonPrimitive.java +++ b/src/main/java/org/versly/rest/wsdoc/impl/JsonPrimitive.java @@ -26,7 +26,7 @@ public class JsonPrimitive implements JsonType, Serializable { - private static final Map _primitiveTypeNamesByJavaTypeName = new HashMap(); + private static final Map _primitiveTypeNamesByJavaTypeName = new HashMap<>(); static { _primitiveTypeNamesByJavaTypeName.put(Object.class.getName(), "object"); diff --git a/src/main/java/org/versly/rest/wsdoc/impl/RestDocumentation.java b/src/main/java/org/versly/rest/wsdoc/impl/RestDocumentation.java index 70e61e5..e417f18 100644 --- a/src/main/java/org/versly/rest/wsdoc/impl/RestDocumentation.java +++ b/src/main/java/org/versly/rest/wsdoc/impl/RestDocumentation.java @@ -22,7 +22,7 @@ public class RestDocumentation implements Serializable { - private Map _resources = new LinkedHashMap(); + private Map _resources = new LinkedHashMap<>(); public Collection getResources() { return _resources.values(); @@ -71,7 +71,7 @@ public RestDocumentation filter(Iterable excludePatterns) { public class Resource implements Serializable { private String path; - private Collection _methods = new LinkedList(); + private Collection _methods = new LinkedList<>(); public Resource(String path) { this.path = path; @@ -168,7 +168,7 @@ public String getKey() { public class UrlFields implements Serializable { - private Map _jsonTypes = new LinkedHashMap(); + private Map _jsonTypes = new LinkedHashMap<>(); public Map getFields() { return _jsonTypes; diff --git a/src/main/resources/org/versly/rest/wsdoc/RestDocumentation.ftl b/src/main/resources/org/versly/rest/wsdoc/RestDocumentation.ftl index 86aa38f..0609a60 100644 --- a/src/main/resources/org/versly/rest/wsdoc/RestDocumentation.ftl +++ b/src/main/resources/org/versly/rest/wsdoc/RestDocumentation.ftl @@ -29,7 +29,7 @@ div.resource-docs { padding-bottom: 20px; } div.url-info { padding-bottom: 20px; } - div.url-info table { width: 400px; border-spacing: 0px; } + div.url-info table { width: 400px; border-spacing: 0; } div.url-info thead td { border-bottom: 1px dashed gray; } .url-info-key { font-family: monospace; } .url-info-expected-type { font-family: monospace; } @@ -66,7 +66,7 @@ <#list docs as doc> <#list doc.resources as resource> <#list resource.requestMethodDocs as methodDoc> - +
${methodDoc.requestMethod} diff --git a/src/test/resources/org/versly/rest/wsdoc/springmvc/SnowReportController.java b/src/test/resources/org/versly/rest/wsdoc/springmvc/SnowReportController.java index edf0e28..4a0ab1f 100755 --- a/src/test/resources/org/versly/rest/wsdoc/springmvc/SnowReportController.java +++ b/src/test/resources/org/versly/rest/wsdoc/springmvc/SnowReportController.java @@ -16,6 +16,7 @@ package org.versly.rest.wsdoc.springmvc; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -32,6 +33,7 @@ public SnowReport getReportForMountain( } + @JsonIgnoreProperties({"mountainName"}) public interface SnowReport { public String getMountainName(); public double getTemperatureInFahrenheit();