You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2014/12/30 11:42:22 UTC
[06/29] camel git commit: CAMEL-7999: apt compiler to generate json
schema documentation for the model,
whcih we later use to enrich the xml xsd to include documentation. Work in
progress.
CAMEL-7999: apt compiler to generate json schema documentation for the model, whcih we later use to enrich the xml xsd to include documentation. Work in progress.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/1ee75b43
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/1ee75b43
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/1ee75b43
Branch: refs/heads/master
Commit: 1ee75b4321c81ebbb2c82c6516f2b4a71c5a6a13
Parents: e505d03
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Dec 25 18:06:34 2014 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Tue Dec 30 10:56:39 2014 +0100
----------------------------------------------------------------------
.../tools/apt/AbstractAnnotationProcessor.java | 43 +++++++++++-
.../tools/apt/EndpointAnnotationProcessor.java | 10 +--
.../camel/tools/apt/JsonSchemaHelper.java | 13 +++-
.../ModelDocumentationAnnotationProcessor.java | 70 +++++++++++++++-----
4 files changed, 112 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/1ee75b43/tooling/apt/src/main/java/org/apache/camel/tools/apt/AbstractAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/AbstractAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/AbstractAnnotationProcessor.java
index e558869..f4806b3 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/AbstractAnnotationProcessor.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/AbstractAnnotationProcessor.java
@@ -34,6 +34,7 @@ import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeKind;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic;
@@ -49,7 +50,7 @@ import static org.apache.camel.tools.apt.Strings.isNullOrEmpty;
*/
public abstract class AbstractAnnotationProcessor extends AbstractProcessor {
- protected String findJavaDoc(Elements elementUtils, VariableElement fieldElement, String fieldName, TypeElement classElement) {
+ protected String findJavaDoc(Elements elementUtils, VariableElement fieldElement, String fieldName, TypeElement classElement, boolean builderPattern) {
String answer = elementUtils.getDocComment(fieldElement);
if (isNullOrEmpty(answer)) {
String setter = "set" + fieldName.substring(0, 1).toUpperCase();
@@ -60,7 +61,7 @@ public abstract class AbstractAnnotationProcessor extends AbstractProcessor {
List<ExecutableElement> methods = ElementFilter.methodsIn(classElement.getEnclosedElements());
for (ExecutableElement method : methods) {
String methodName = method.getSimpleName().toString();
- if (setter.equals(methodName) && method.getParameters().size() == 1) {
+ if (setter.equals(methodName) && method.getParameters().size() == 1 && method.getReturnType().getKind().equals(TypeKind.VOID)) {
String doc = elementUtils.getDocComment(method);
if (!isNullOrEmpty(doc)) {
answer = doc;
@@ -92,6 +93,22 @@ public abstract class AbstractAnnotationProcessor extends AbstractProcessor {
}
}
}
+
+ // lets try builder pattern
+ if (answer == null && builderPattern) {
+ // lets find the getter
+ methods = ElementFilter.methodsIn(classElement.getEnclosedElements());
+ for (ExecutableElement method : methods) {
+ String methodName = method.getSimpleName().toString();
+ if (fieldName.equals(methodName) && method.getParameters().size() == 1) {
+ String doc = elementUtils.getDocComment(method);
+ if (!isNullOrEmpty(doc)) {
+ answer = doc;
+ break;
+ }
+ }
+ }
+ }
}
return answer;
}
@@ -136,6 +153,28 @@ public abstract class AbstractAnnotationProcessor extends AbstractProcessor {
return null;
}
+ protected void findTypeElementChildren(RoundEnvironment roundEnv, Set<TypeElement> found, String superClassName) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ int idx = superClassName.lastIndexOf('.');
+ if (idx > 0) {
+ String packageName = superClassName.substring(0, idx);
+ PackageElement pe = elementUtils.getPackageElement(packageName);
+ if (pe != null) {
+ List<? extends Element> enclosedElements = pe.getEnclosedElements();
+ for (Element rootElement : enclosedElements) {
+ if (rootElement instanceof TypeElement) {
+ TypeElement typeElement = (TypeElement) rootElement;
+ String aSuperClassName = canonicalClassName(typeElement.getSuperclass().toString());
+ if (superClassName.equals(aSuperClassName)) {
+ found.add(typeElement);
+ }
+ }
+ }
+ }
+ }
+ }
+
/**
* Helper method to produce class output text file using the given handler
*/
http://git-wip-us.apache.org/repos/asf/camel/blob/1ee75b43/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
index f51c903..a091ab7 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
@@ -190,7 +190,8 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
buffer.append(",");
}
buffer.append("\n ");
- buffer.append(JsonSchemaHelper.toJson(path.getName(), "path", null, path.getType(), "", path.getDocumentation(), path.isEnumType(), path.getEnums()));
+ buffer.append(JsonSchemaHelper.toJson(path.getName(), "path", null, path.getType(), "", path.getDocumentation(),
+ path.isEnumType(), path.getEnums(), false, null));
}
// and then regular parameter options
@@ -204,7 +205,8 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
// as its json we need to sanitize the docs
String doc = entry.getDocumentationWithNotes();
doc = sanitizeDescription(doc, false);
- buffer.append(JsonSchemaHelper.toJson(entry.getName(), "parameter", null, entry.getType(), entry.getDefaultValue(), doc, entry.isEnumType(), entry.getEnums()));
+ buffer.append(JsonSchemaHelper.toJson(entry.getName(), "parameter", null, entry.getType(), entry.getDefaultValue(), doc,
+ entry.isEnumType(), entry.getEnums(), false, null));
}
buffer.append("\n }");
@@ -336,7 +338,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
String fieldTypeName = fieldType.toString();
TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement, false);
if (isNullOrEmpty(docComment)) {
docComment = path.description();
}
@@ -388,7 +390,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
}
findClassProperties(writer, roundEnv, endpointPaths, endpointOptions, fieldTypeElement, nestedPrefix);
} else {
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement, false);
if (isNullOrEmpty(docComment)) {
docComment = param.description();
}
http://git-wip-us.apache.org/repos/asf/camel/blob/1ee75b43/tooling/apt/src/main/java/org/apache/camel/tools/apt/JsonSchemaHelper.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/JsonSchemaHelper.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/JsonSchemaHelper.java
index fd54723..42a2699 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/JsonSchemaHelper.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/JsonSchemaHelper.java
@@ -30,7 +30,8 @@ final class JsonSchemaHelper {
private JsonSchemaHelper() {
}
- public static String toJson(String name, String kind, Boolean required, String type, String defaultValue, String description, boolean enumType, Set<String> enums) {
+ public static String toJson(String name, String kind, Boolean required, String type, String defaultValue, String description,
+ boolean enumType, Set<String> enums, boolean oneOfType, Set<String> oneOffTypes) {
String typeName = JsonSchemaHelper.getType(type, enumType);
StringBuilder sb = new StringBuilder();
@@ -53,6 +54,16 @@ final class JsonSchemaHelper {
sb.append(", \"enum\": [ ");
sb.append(enumValues.toString());
sb.append(" ]");
+ } else if (oneOfType) {
+ sb.append(Strings.doubleQuote("object"));
+ sb.append(", \"javaType\": \"" + type + "\"");
+ CollectionStringBuffer oneOfValues = new CollectionStringBuffer();
+ for (Object value : oneOffTypes) {
+ oneOfValues.append(Strings.doubleQuote(value.toString()));
+ }
+ sb.append(", \"oneOf\": [ ");
+ sb.append(oneOfValues.toString());
+ sb.append(" ]");
} else if ("array".equals(typeName)) {
sb.append(Strings.doubleQuote("array"));
sb.append(", \"javaType\": \"" + type + "\"");
http://git-wip-us.apache.org/repos/asf/camel/blob/1ee75b43/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelDocumentationAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelDocumentationAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelDocumentationAnnotationProcessor.java
index c81910c..215f8bd 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelDocumentationAnnotationProcessor.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelDocumentationAnnotationProcessor.java
@@ -16,16 +16,10 @@
*/
package org.apache.camel.tools.apt;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
import java.io.PrintWriter;
-import java.io.Writer;
-import java.net.URI;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-import javax.annotation.processing.Filer;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
@@ -37,8 +31,6 @@ import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
-import javax.tools.FileObject;
-import javax.tools.StandardLocation;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@@ -47,12 +39,16 @@ import static org.apache.camel.tools.apt.JsonSchemaHelper.sanitizeDescription;
import static org.apache.camel.tools.apt.Strings.canonicalClassName;
import static org.apache.camel.tools.apt.Strings.isNullOrEmpty;
-// TODO: add support for @XmlElement @XmlElementRef
+// TODO: add support for @XmlElementRef (eg as used by choice)
@SupportedAnnotationTypes({"javax.xml.bind.annotation.*"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationProcessor {
+ // special when using expression/predicates in the model
+ private final String ONE_OF_TYPE_NAME = "org.apache.camel.model.ExpressionSubElementDefinition";
+ private final String ONE_OF_LANGUAGES = "org.apache.camel.model.language.ExpressionDefinition";
+
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
@@ -79,8 +75,15 @@ public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationPro
final XmlRootElement rootElement = classElement.getAnnotation(XmlRootElement.class);
final String name = rootElement.name();
+ // lets use the xsd name as the file name
+ String fileName;
+ if (isNullOrEmpty(name) || "##default".equals(name)) {
+ fileName = classElement.getSimpleName().toString() + ".json";
+ } else {
+ fileName = name + ".json";
+ }
+
// write json schema
- String fileName = classElement.getSimpleName().toString() + ".json";
Func1<PrintWriter, Void> handler = new Func1<PrintWriter, Void>() {
@Override
public Void call(PrintWriter writer) {
@@ -125,7 +128,8 @@ public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationPro
// as its json we need to sanitize the docs
String doc = entry.getDocumentationWithNotes();
doc = sanitizeDescription(doc, false);
- buffer.append(JsonSchemaHelper.toJson(entry.getName(), entry.getKind(), entry.isRequired(), entry.getType(), entry.getDefaultValue(), doc, entry.isEnumType(), entry.getEnums()));
+ buffer.append(JsonSchemaHelper.toJson(entry.getName(), entry.getKind(), entry.isRequired(), entry.getType(), entry.getDefaultValue(), doc,
+ entry.isEnumType(), entry.getEnums(), entry.isOneOf(), entry.getOneOfTypes()));
}
buffer.append("\n }");
@@ -176,7 +180,7 @@ public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationPro
String fieldTypeName = fieldType.toString();
TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement, true);
boolean required = attribute.required();
// gather enums
@@ -194,13 +198,14 @@ public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationPro
}
}
- EipOption ep = new EipOption(name, "attribute", fieldTypeName, required, "", "", docComment, isEnum, enums);
+ EipOption ep = new EipOption(name, "attribute", fieldTypeName, required, "", "", docComment, isEnum, enums, false, null);
eipOptions.add(ep);
}
XmlElement element = fieldElement.getAnnotation(XmlElement.class);
fieldName = fieldElement.getSimpleName().toString();
if (element != null) {
+ String kind = "element";
String name = element.name();
if (isNullOrEmpty(name) || "##default".equals(name)) {
name = fieldName;
@@ -210,7 +215,7 @@ public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationPro
String fieldTypeName = fieldType.toString();
TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement, true);
boolean required = element.required();
// gather enums
@@ -228,10 +233,29 @@ public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationPro
}
}
- EipOption ep = new EipOption(name, "element", fieldTypeName, required, "", "", docComment, isEnum, enums);
+ // gather oneOf expression/predicates which uses language
+ Set<String> oneOfTypes = new LinkedHashSet<String>();
+ boolean isOneOf = ONE_OF_TYPE_NAME.equals(fieldTypeName);
+ if (isOneOf) {
+ TypeElement languages = findTypeElement(roundEnv, ONE_OF_LANGUAGES);
+ String superClassName = canonicalClassName(languages.toString());
+ // find all classes that has that superClassName
+ Set<TypeElement> children = new LinkedHashSet<TypeElement>();
+ findTypeElementChildren(roundEnv, children, superClassName);
+ for (TypeElement child : children) {
+ XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class);
+ if (rootElement != null) {
+ String childName = rootElement.name();
+ if (childName != null) {
+ oneOfTypes.add(childName);
+ }
+ }
+ }
+ }
+
+ EipOption ep = new EipOption(name, kind, fieldTypeName, required, "", "", docComment, isEnum, enums, isOneOf, oneOfTypes);
eipOptions.add(ep);
}
-
}
// check super classes which may also have @UriParam fields
@@ -291,9 +315,11 @@ public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationPro
private String documentation;
private boolean enumType;
private Set<String> enums;
+ private boolean oneOf;
+ private Set<String> oneOfTypes;
private EipOption(String name, String kind, String type, boolean required, String defaultValue, String defaultValueNote,
- String documentation, boolean enumType, Set<String> enums) {
+ String documentation, boolean enumType, Set<String> enums, boolean oneOf, Set<String> oneOfTypes) {
this.name = name;
this.kind = kind;
this.type = type;
@@ -303,6 +329,8 @@ public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationPro
this.documentation = documentation;
this.enumType = enumType;
this.enums = enums;
+ this.oneOf = oneOf;
+ this.oneOfTypes = oneOfTypes;
}
public String getName() {
@@ -358,6 +386,14 @@ public class ModelDocumentationAnnotationProcessor extends AbstractAnnotationPro
return enums;
}
+ public boolean isOneOf() {
+ return oneOf;
+ }
+
+ public Set<String> getOneOfTypes() {
+ return oneOfTypes;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {