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 2016/08/11 08:07:07 UTC
[1/4] camel git commit: CAMEL-9482: Adjust the apt to make camel-core
compile again,
seems like we need to merge the core/spring into a single apt as the compiler
cannot do both on camel-core for some odd reason.
Repository: camel
Updated Branches:
refs/heads/master bbb7ff941 -> 8a18e2849
http://git-wip-us.apache.org/repos/asf/camel/blob/8a18e284/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessor.java
new file mode 100644
index 0000000..064872f
--- /dev/null
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/SpringAnnotationProcessor.java
@@ -0,0 +1,689 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.tools.apt;
+
+import java.io.PrintWriter;
+import java.util.Comparator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.annotation.processing.ProcessingEnvironment;
+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.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+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.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.tools.apt.helper.JsonSchemaHelper;
+import org.apache.camel.tools.apt.helper.Strings;
+
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findJavaDoc;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findTypeElement;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.processFile;
+import static org.apache.camel.tools.apt.helper.JsonSchemaHelper.sanitizeDescription;
+import static org.apache.camel.tools.apt.helper.Strings.canonicalClassName;
+import static org.apache.camel.tools.apt.helper.Strings.isNullOrEmpty;
+import static org.apache.camel.tools.apt.helper.Strings.safeNull;
+
+/**
+ * Process camel-spring's <camelContext> and generate json schema documentation
+ */
+@SupportedAnnotationTypes({"javax.xml.bind.annotation.*", "org.apache.camel.spi.Label"})
+@SupportedSourceVersion(SourceVersion.RELEASE_8)
+public class SpringAnnotationProcessor {
+
+ protected void processModelClass(final ProcessingEnvironment processingEnv, final RoundEnvironment roundEnv, final TypeElement classElement) {
+ final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
+ String packageName = javaTypeName.substring(0, javaTypeName.lastIndexOf("."));
+
+ // skip abstract classes
+ if (classElement.getModifiers().contains(Modifier.ABSTRACT)) {
+ return;
+ }
+
+ final XmlRootElement rootElement = classElement.getAnnotation(XmlRootElement.class);
+ if (rootElement == null) {
+ return;
+ }
+
+ String aName = rootElement.name();
+ if (isNullOrEmpty(aName) || "##default".equals(aName)) {
+ XmlType typeElement = classElement.getAnnotation(XmlType.class);
+ aName = typeElement.name();
+ }
+ final String name = aName;
+
+ // 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
+ Func1<PrintWriter, Void> handler = new Func1<PrintWriter, Void>() {
+ @Override
+ public Void call(PrintWriter writer) {
+ writeJSonSchemeDocumentation(processingEnv, writer, roundEnv, classElement, rootElement, javaTypeName, name);
+ return null;
+ }
+ };
+ processFile(processingEnv, packageName, fileName, handler);
+ }
+
+ protected void writeJSonSchemeDocumentation(ProcessingEnvironment processingEnv, PrintWriter writer, RoundEnvironment roundEnv,
+ TypeElement classElement, XmlRootElement rootElement,
+ String javaTypeName, String modelName) {
+ // gather eip information
+ EipModel eipModel = findEipModelProperties(processingEnv, roundEnv, classElement, javaTypeName, modelName);
+
+ // collect eip information
+ Set<EipOption> eipOptions = new TreeSet<EipOption>(new EipOptionComparator(eipModel));
+ findClassProperties(processingEnv, writer, roundEnv, eipOptions, classElement, classElement, "", modelName);
+
+ String json = createParameterJsonSchema(eipModel, eipOptions);
+ writer.println(json);
+ }
+
+ public String createParameterJsonSchema(EipModel eipModel, Set<EipOption> options) {
+ StringBuilder buffer = new StringBuilder("{");
+ // eip model
+ buffer.append("\n \"model\": {");
+ buffer.append("\n \"kind\": \"").append("model").append("\",");
+ buffer.append("\n \"name\": \"").append(eipModel.getName()).append("\",");
+ if (eipModel.getTitle() != null) {
+ buffer.append("\n \"title\": \"").append(eipModel.getTitle()).append("\",");
+ } else {
+ // fallback and use name as title
+ buffer.append("\n \"title\": \"").append(asTitle(eipModel.getName())).append("\",");
+ }
+ buffer.append("\n \"description\": \"").append(safeNull(eipModel.getDescription())).append("\",");
+ buffer.append("\n \"javaType\": \"").append(eipModel.getJavaType()).append("\",");
+ buffer.append("\n \"label\": \"").append(safeNull(eipModel.getLabel())).append("\"");
+ buffer.append("\n },");
+
+ buffer.append("\n \"properties\": {");
+ boolean first = true;
+ for (EipOption entry : options) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(",");
+ }
+ buffer.append("\n ");
+ // as its json we need to sanitize the docs
+ String doc = entry.getDocumentation();
+ doc = sanitizeDescription(doc, false);
+ buffer.append(JsonSchemaHelper.toJson(entry.getName(), entry.getKind(), entry.isRequired(), entry.getType(), entry.getDefaultValue(), doc,
+ entry.isDeprecated(), false, null, null, entry.isEnumType(), entry.getEnums(), entry.isOneOf(), entry.getOneOfTypes(), null, null, false));
+ }
+ buffer.append("\n }");
+
+ buffer.append("\n}\n");
+ return buffer.toString();
+ }
+
+ protected EipModel findEipModelProperties(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement classElement, String javaTypeName, String name) {
+ EipModel model = new EipModel();
+ model.setJavaType(javaTypeName);
+ model.setName(name);
+
+ Metadata metadata = classElement.getAnnotation(Metadata.class);
+ if (metadata != null) {
+ if (!Strings.isNullOrEmpty(metadata.label())) {
+ model.setLabel(metadata.label());
+ }
+ if (!Strings.isNullOrEmpty(metadata.title())) {
+ model.setTitle(metadata.title());
+ }
+ }
+
+ // favor to use class javadoc of component as description
+ if (model.getJavaType() != null) {
+ Elements elementUtils = processingEnv.getElementUtils();
+ TypeElement typeElement = findTypeElement(processingEnv, roundEnv, model.getJavaType());
+ if (typeElement != null) {
+ String doc = elementUtils.getDocComment(typeElement);
+ if (doc != null) {
+ // need to sanitize the description first (we only want a summary)
+ doc = sanitizeDescription(doc, true);
+ // the javadoc may actually be empty, so only change the doc if we got something
+ if (!Strings.isNullOrEmpty(doc)) {
+ model.setDescription(doc);
+ }
+ }
+ }
+ }
+
+ return model;
+ }
+
+ protected void findClassProperties(ProcessingEnvironment processingEnv, PrintWriter writer, RoundEnvironment roundEnv, Set<EipOption> eipOptions,
+ TypeElement originalClassType, TypeElement classElement, String prefix, String modelName) {
+ while (true) {
+ List<VariableElement> fieldElements = ElementFilter.fieldsIn(classElement.getEnclosedElements());
+ for (VariableElement fieldElement : fieldElements) {
+
+ String fieldName = fieldElement.getSimpleName().toString();
+
+ XmlAttribute attribute = fieldElement.getAnnotation(XmlAttribute.class);
+ if (attribute != null) {
+ boolean skip = processAttribute(processingEnv, roundEnv, originalClassType, classElement, fieldElement, fieldName, attribute, eipOptions, prefix, modelName);
+ if (skip) {
+ continue;
+ }
+ }
+
+ XmlElements elements = fieldElement.getAnnotation(XmlElements.class);
+ if (elements != null) {
+ processElements(processingEnv, roundEnv, classElement, elements, fieldElement, eipOptions, prefix);
+ }
+
+ XmlElementRef elementRef = fieldElement.getAnnotation(XmlElementRef.class);
+ if (elementRef != null) {
+ processElement(processingEnv, roundEnv, classElement, null, elementRef, fieldElement, eipOptions, prefix);
+ }
+
+ XmlElement element = fieldElement.getAnnotation(XmlElement.class);
+ if (element != null) {
+ if ("rests".equals(fieldName)) {
+ processRests(roundEnv, classElement, element, fieldElement, fieldName, eipOptions, prefix);
+ } else if ("routes".equals(fieldName)) {
+ processRoutes(roundEnv, classElement, element, fieldElement, fieldName, eipOptions, prefix);
+ } else {
+ processElement(processingEnv, roundEnv, classElement, element, null, fieldElement, eipOptions, prefix);
+ }
+ }
+ }
+
+ // check super classes which may also have fields
+ TypeElement baseTypeElement = null;
+ TypeMirror superclass = classElement.getSuperclass();
+ if (superclass != null) {
+ String superClassName = canonicalClassName(superclass.toString());
+ baseTypeElement = findTypeElement(processingEnv, roundEnv, superClassName);
+ }
+ if (baseTypeElement != null) {
+ classElement = baseTypeElement;
+ } else {
+ break;
+ }
+ }
+ }
+
+ private boolean processAttribute(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement originalClassType,
+ TypeElement classElement, VariableElement fieldElement,
+ String fieldName, XmlAttribute attribute, Set<EipOption> eipOptions, String prefix, String modelName) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ String name = attribute.name();
+ if (isNullOrEmpty(name) || "##default".equals(name)) {
+ name = fieldName;
+ }
+
+ name = prefix + name;
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+ TypeElement fieldTypeElement = findTypeElement(processingEnv, roundEnv, fieldTypeName);
+
+ String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
+ if (isNullOrEmpty(docComment)) {
+ Metadata metadata = fieldElement.getAnnotation(Metadata.class);
+ docComment = metadata != null ? metadata.description() : null;
+ }
+ boolean required = attribute.required();
+ // metadata may overrule element required
+ required = findRequired(fieldElement, required);
+
+ // gather enums
+ Set<String> enums = new TreeSet<String>();
+ boolean isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
+ if (isEnum) {
+ TypeElement enumClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString());
+ // find all the enum constants which has the possible enum value that can be used
+ List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
+ for (VariableElement var : fields) {
+ if (var.getKind() == ElementKind.ENUM_CONSTANT) {
+ String val = var.toString();
+ enums.add(val);
+ }
+ }
+ }
+
+ boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
+
+ // special for id as its inherited from camel-core
+ if ("id".equals(name) && isNullOrEmpty(docComment)) {
+ if ("CamelContextFactoryBean".equals(originalClassType.getSimpleName().toString())) {
+ docComment = "Sets the id (name) of this CamelContext";
+ } else {
+ docComment = "Sets the id of this node";
+ }
+ }
+
+ EipOption ep = new EipOption(name, "attribute", fieldTypeName, required, defaultValue, docComment, deprecated, isEnum, enums, false, null);
+ eipOptions.add(ep);
+
+ return false;
+ }
+
+ /**
+ * Special for processing an @XmlElement routes field
+ */
+ private void processRoutes(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElement element,
+ VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
+
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ Set<String> oneOfTypes = new TreeSet<String>();
+ oneOfTypes.add("route");
+
+ EipOption ep = new EipOption("route", "element", fieldTypeName, false, "", "Contains the Camel routes", false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+
+ /**
+ * Special for processing an @XmlElement rests field
+ */
+ private void processRests(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElement element,
+ VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
+
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ Set<String> oneOfTypes = new TreeSet<String>();
+ oneOfTypes.add("rest");
+
+ EipOption ep = new EipOption("rest", "element", fieldTypeName, false, "", "Contains the rest services defined using the rest-dsl", false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+
+ private void processElement(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv,
+ TypeElement classElement, XmlElement element, XmlElementRef elementRef, VariableElement fieldElement,
+ Set<EipOption> eipOptions, String prefix) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ String fieldName;
+ fieldName = fieldElement.getSimpleName().toString();
+ if (element != null || elementRef != null) {
+
+ String kind = "element";
+ String name = element != null ? element.name() : elementRef.name();
+ if (isNullOrEmpty(name) || "##default".equals(name)) {
+ name = fieldName;
+ }
+ name = prefix + name;
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+ TypeElement fieldTypeElement = findTypeElement(processingEnv, roundEnv, fieldTypeName);
+
+ String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
+ if (isNullOrEmpty(docComment)) {
+ Metadata metadata = fieldElement.getAnnotation(Metadata.class);
+ docComment = metadata != null ? metadata.description() : null;
+ }
+ boolean required = element != null ? element.required() : elementRef.required();
+ // metadata may overrule element required
+ required = findRequired(fieldElement, required);
+
+ // gather enums
+ Set<String> enums = new LinkedHashSet<String>();
+ boolean isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
+ if (isEnum) {
+ TypeElement enumClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString());
+ // find all the enum constants which has the possible enum value that can be used
+ List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
+ for (VariableElement var : fields) {
+ if (var.getKind() == ElementKind.ENUM_CONSTANT) {
+ String val = var.toString();
+ enums.add(val);
+ }
+ }
+ }
+
+ // is it a definition/factory-bean type then its a oneOf
+ TreeSet oneOfTypes = new TreeSet<String>();
+ if (fieldTypeName.endsWith("Definition") || fieldTypeName.endsWith("FactoryBean")) {
+ TypeElement definitionClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString());
+ if (definitionClass != null) {
+ XmlRootElement rootElement = definitionClass.getAnnotation(XmlRootElement.class);
+ if (rootElement != null) {
+ String childName = rootElement.name();
+ if (childName != null) {
+ oneOfTypes.add(childName);
+ }
+ }
+ }
+ } else if (fieldTypeName.endsWith("Definition>") || fieldTypeName.endsWith("FactoryBean>")) {
+ // its a list so we need to load the generic type
+ String typeName = Strings.between(fieldTypeName, "<", ">");
+ TypeElement definitionClass = findTypeElement(processingEnv, roundEnv, typeName);
+ if (definitionClass != null) {
+ XmlRootElement rootElement = definitionClass.getAnnotation(XmlRootElement.class);
+ if (rootElement != null) {
+ String childName = rootElement.name();
+ if (childName != null) {
+ oneOfTypes.add(childName);
+ }
+ }
+ }
+ }
+ boolean oneOf = !oneOfTypes.isEmpty();
+
+ boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
+
+ EipOption ep = new EipOption(name, kind, fieldTypeName, required, defaultValue, docComment, deprecated, isEnum, enums, oneOf, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ private void processElements(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv,
+ TypeElement classElement, XmlElements elements, VariableElement fieldElement,
+ Set<EipOption> eipOptions, String prefix) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ String fieldName;
+ fieldName = fieldElement.getSimpleName().toString();
+ if (elements != null) {
+ String kind = "element";
+ String name = fieldName;
+ name = prefix + name;
+
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
+ if (isNullOrEmpty(docComment)) {
+ Metadata metadata = fieldElement.getAnnotation(Metadata.class);
+ docComment = metadata != null ? metadata.description() : null;
+ }
+ boolean required = false;
+ required = findRequired(fieldElement, required);
+
+ // gather oneOf of the elements
+ Set<String> oneOfTypes = new TreeSet<String>();
+ for (XmlElement element : elements.value()) {
+ String child = element.name();
+ oneOfTypes.add(child);
+ }
+
+ EipOption ep = new EipOption(name, kind, fieldTypeName, required, defaultValue, docComment, false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ private String findDefaultValue(VariableElement fieldElement, String fieldTypeName) {
+ String defaultValue = null;
+ Metadata metadata = fieldElement.getAnnotation(Metadata.class);
+ if (metadata != null) {
+ if (!Strings.isNullOrEmpty(metadata.defaultValue())) {
+ defaultValue = metadata.defaultValue();
+ }
+ }
+ if (defaultValue == null) {
+ // if its a boolean type, then we use false as the default
+ if ("boolean".equals(fieldTypeName) || "java.lang.Boolean".equals(fieldTypeName)) {
+ defaultValue = "false";
+ }
+ }
+
+ return defaultValue;
+ }
+
+ private boolean findRequired(VariableElement fieldElement, boolean defaultValue) {
+ Metadata metadata = fieldElement.getAnnotation(Metadata.class);
+ if (metadata != null) {
+ if (!Strings.isNullOrEmpty(metadata.required())) {
+ defaultValue = "true".equals(metadata.required());
+ }
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Capitializes the name as a title
+ *
+ * @param name the name
+ * @return as a title
+ */
+ private static String asTitle(String name) {
+ StringBuilder sb = new StringBuilder();
+ for (char c : name.toCharArray()) {
+ boolean upper = Character.isUpperCase(c);
+ boolean first = sb.length() == 0;
+ if (first) {
+ sb.append(Character.toUpperCase(c));
+ } else if (upper) {
+ sb.append(' ');
+ sb.append(c);
+ } else {
+ sb.append(Character.toLowerCase(c));
+ }
+ }
+ return sb.toString().trim();
+ }
+
+ private static final class EipModel {
+
+ private String name;
+ private String title;
+ private String javaType;
+ private String label;
+ private String description;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getJavaType() {
+ return javaType;
+ }
+
+ public void setJavaType(String javaType) {
+ this.javaType = javaType;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ }
+
+ private static final class EipOption {
+
+ private String name;
+ private String kind;
+ private String type;
+ private boolean required;
+ private String defaultValue;
+ private String documentation;
+ private boolean deprecated;
+ 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 documentation, boolean deprecated,
+ boolean enumType, Set<String> enums, boolean oneOf, Set<String> oneOfTypes) {
+ this.name = name;
+ this.kind = kind;
+ this.type = type;
+ this.required = required;
+ this.defaultValue = defaultValue;
+ this.documentation = documentation;
+ this.deprecated = deprecated;
+ this.enumType = enumType;
+ this.enums = enums;
+ this.oneOf = oneOf;
+ this.oneOfTypes = oneOfTypes;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getKind() {
+ return kind;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ public String getDocumentation() {
+ return documentation;
+ }
+
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
+ public boolean isEnumType() {
+ return enumType;
+ }
+
+ public Set<String> getEnums() {
+ return enums;
+ }
+
+ public boolean isOneOf() {
+ return oneOf;
+ }
+
+ public Set<String> getOneOfTypes() {
+ return oneOfTypes;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ EipOption that = (EipOption) o;
+
+ if (!name.equals(that.name)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+ }
+
+ private static final class EipOptionComparator implements Comparator<EipOption> {
+
+ private final EipModel model;
+
+ private EipOptionComparator(EipModel model) {
+ this.model = model;
+ }
+
+ @Override
+ public int compare(EipOption o1, EipOption o2) {
+ int weigth = weigth(o1);
+ int weigth2 = weigth(o2);
+
+ if (weigth == weigth2) {
+ // keep the current order
+ return 1;
+ } else {
+ // sort according to weight
+ return weigth2 - weigth;
+ }
+ }
+
+ private int weigth(EipOption o) {
+ String name = o.getName();
+
+ // these should be first
+ if ("expression".equals(name)) {
+ return 10;
+ }
+
+ // these should be last
+ if ("description".equals(name)) {
+ return -10;
+ } else if ("id".equals(name)) {
+ return -9;
+ } else if ("pattern".equals(name) && "to".equals(model.getName())) {
+ // and pattern only for the to model
+ return -8;
+ }
+ return 0;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/8a18e284/tooling/apt/src/main/resources/META-INF/services/javax.annotation.processing.Processor
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/tooling/apt/src/main/resources/META-INF/services/javax.annotation.processing.Processor
index 4e19db2..065c7b0 100644
--- a/tooling/apt/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/tooling/apt/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-org.apache.camel.tools.apt.EipAnnotationProcessor
+
+### only specify ModelAnnotationProcessor as it delegates to CoreEip or Spring accordingly
+org.apache.camel.tools.apt.ModelAnnotationProcessor
org.apache.camel.tools.apt.EndpointAnnotationProcessor
-org.apache.camel.tools.apt.CamelContextAnnotationProcessor
[3/4] camel git commit: CAMEL-9482: Adjust the apt to make camel-core
compile again,
seems like we need to merge the core/spring into a single apt as the compiler
cannot do both on camel-core for some odd reason.
Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/8a18e284/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessor.java
new file mode 100644
index 0000000..be2783f
--- /dev/null
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/CoreEipAnnotationProcessor.java
@@ -0,0 +1,1127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.tools.apt;
+
+import java.io.PrintWriter;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+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.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.tools.apt.helper.JsonSchemaHelper;
+import org.apache.camel.tools.apt.helper.Strings;
+
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findJavaDoc;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findTypeElement;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findTypeElementChildren;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.hasSuperClass;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.processFile;
+import static org.apache.camel.tools.apt.helper.JsonSchemaHelper.sanitizeDescription;
+import static org.apache.camel.tools.apt.helper.Strings.canonicalClassName;
+import static org.apache.camel.tools.apt.helper.Strings.isNullOrEmpty;
+import static org.apache.camel.tools.apt.helper.Strings.safeNull;
+
+/**
+ * Process all camel-core's model classes (EIPs and DSL) and generate json schema documentation
+ */
+public class CoreEipAnnotationProcessor {
+
+ // special when using expression/predicates in the model
+ private static final String ONE_OF_TYPE_NAME = "org.apache.camel.model.ExpressionSubElementDefinition";
+ private static final String[] ONE_OF_LANGUAGES = new String[]{
+ "org.apache.camel.model.language.ExpressionDefinition",
+ "org.apache.camel.model.language.NamespaceAwareExpression"
+ };
+ // special for inputs (these classes have sub classes, so we use this to find all classes)
+ private static final String[] ONE_OF_INPUTS = new String[]{
+ "org.apache.camel.model.ProcessorDefinition",
+ "org.apache.camel.model.VerbDefinition"
+ };
+ // special for outputs (these classes have sub classes, so we use this to find all classes)
+ private static final String[] ONE_OF_OUTPUTS = new String[]{
+ "org.apache.camel.model.ProcessorDefinition",
+ "org.apache.camel.model.NoOutputDefinition",
+ "org.apache.camel.model.OutputDefinition",
+ "org.apache.camel.model.ExpressionNode",
+ "org.apache.camel.model.NoOutputExpressionNode",
+ "org.apache.camel.model.SendDefinition",
+ "org.apache.camel.model.InterceptDefinition",
+ "org.apache.camel.model.WhenDefinition",
+ "org.apache.camel.model.ToDynamicDefinition"
+ };
+ // special for verbs (these classes have sub classes, so we use this to find all classes)
+ private static final String[] ONE_OF_VERBS = new String[]{
+ "org.apache.camel.model.rest.VerbDefinition"
+ };
+
+ private boolean skipUnwanted = true;
+
+ protected void processModelClass(final ProcessingEnvironment processingEnv, final RoundEnvironment roundEnv, final TypeElement classElement) {
+ final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
+ String packageName = javaTypeName.substring(0, javaTypeName.lastIndexOf("."));
+
+ // skip abstract classes
+ if (classElement.getModifiers().contains(Modifier.ABSTRACT)) {
+ return;
+ }
+
+ // skip unwanted classes which are "abstract" holders
+ if (skipUnwanted) {
+ if (classElement.getQualifiedName().toString().equals(ONE_OF_TYPE_NAME)) {
+ return;
+ }
+ }
+
+ final XmlRootElement rootElement = classElement.getAnnotation(XmlRootElement.class);
+ if (rootElement == null) {
+ return;
+ }
+
+ String aName = rootElement.name();
+ if (isNullOrEmpty(aName) || "##default".equals(aName)) {
+ XmlType typeElement = classElement.getAnnotation(XmlType.class);
+ aName = typeElement.name();
+ }
+ final String name = aName;
+
+ // 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
+ Func1<PrintWriter, Void> handler = new Func1<PrintWriter, Void>() {
+ @Override
+ public Void call(PrintWriter writer) {
+ writeJSonSchemeDocumentation(processingEnv, writer, roundEnv, classElement, rootElement, javaTypeName, name);
+ return null;
+ }
+ };
+ processFile(processingEnv, packageName, fileName, handler);
+ }
+
+ protected void writeJSonSchemeDocumentation(ProcessingEnvironment processingEnv, PrintWriter writer, RoundEnvironment roundEnv,
+ TypeElement classElement, XmlRootElement rootElement,
+ String javaTypeName, String modelName) {
+ // gather eip information
+ EipModel eipModel = findEipModelProperties(processingEnv, roundEnv, classElement, javaTypeName, modelName);
+
+ // get endpoint information which is divided into paths and options (though there should really only be one path)
+ Set<EipOption> eipOptions = new TreeSet<EipOption>(new EipOptionComparator(eipModel));
+ findClassProperties(processingEnv, writer, roundEnv, eipOptions, classElement, classElement, "", modelName);
+
+ // after we have found all the options then figure out if the model accepts input/output
+ eipModel.setInput(hasInput(processingEnv, roundEnv, classElement));
+ eipModel.setOutput(hasOutput(eipModel, eipOptions));
+
+ String json = createParameterJsonSchema(eipModel, eipOptions);
+ writer.println(json);
+ }
+
+ public String createParameterJsonSchema(EipModel eipModel, Set<EipOption> options) {
+ StringBuilder buffer = new StringBuilder("{");
+ // eip model
+ buffer.append("\n \"model\": {");
+ buffer.append("\n \"kind\": \"").append("model").append("\",");
+ buffer.append("\n \"name\": \"").append(eipModel.getName()).append("\",");
+ if (eipModel.getTitle() != null) {
+ buffer.append("\n \"title\": \"").append(eipModel.getTitle()).append("\",");
+ } else {
+ // fallback and use name as title
+ buffer.append("\n \"title\": \"").append(asTitle(eipModel.getName())).append("\",");
+ }
+ buffer.append("\n \"description\": \"").append(safeNull(eipModel.getDescription())).append("\",");
+ buffer.append("\n \"javaType\": \"").append(eipModel.getJavaType()).append("\",");
+ buffer.append("\n \"label\": \"").append(safeNull(eipModel.getLabel())).append("\",");
+ buffer.append("\n \"input\": \"").append(eipModel.getInput()).append("\",");
+ buffer.append("\n \"output\": \"").append(eipModel.getOutput()).append("\"");
+ buffer.append("\n },");
+
+ buffer.append("\n \"properties\": {");
+ boolean first = true;
+ for (EipOption entry : options) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(",");
+ }
+ buffer.append("\n ");
+ // as its json we need to sanitize the docs
+ String doc = entry.getDocumentation();
+ doc = sanitizeDescription(doc, false);
+ buffer.append(JsonSchemaHelper.toJson(entry.getName(), entry.getKind(), entry.isRequired(), entry.getType(), entry.getDefaultValue(), doc,
+ entry.isDeprecated(), false, null, null, entry.isEnumType(), entry.getEnums(), entry.isOneOf(), entry.getOneOfTypes(), null, null, false));
+ }
+ buffer.append("\n }");
+
+ buffer.append("\n}\n");
+ return buffer.toString();
+ }
+
+ protected EipModel findEipModelProperties(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement classElement, String javaTypeName, String name) {
+ EipModel model = new EipModel();
+ model.setJavaType(javaTypeName);
+ model.setName(name);
+
+ Metadata metadata = classElement.getAnnotation(Metadata.class);
+ if (metadata != null) {
+ if (!Strings.isNullOrEmpty(metadata.label())) {
+ model.setLabel(metadata.label());
+ }
+ if (!Strings.isNullOrEmpty(metadata.title())) {
+ model.setTitle(metadata.title());
+ }
+ }
+
+ // favor to use class javadoc of component as description
+ if (model.getJavaType() != null) {
+ Elements elementUtils = processingEnv.getElementUtils();
+ TypeElement typeElement = findTypeElement(processingEnv, roundEnv, model.getJavaType());
+ if (typeElement != null) {
+ String doc = elementUtils.getDocComment(typeElement);
+ if (doc != null) {
+ // need to sanitize the description first (we only want a summary)
+ doc = sanitizeDescription(doc, true);
+ // the javadoc may actually be empty, so only change the doc if we got something
+ if (!Strings.isNullOrEmpty(doc)) {
+ model.setDescription(doc);
+ }
+ }
+ }
+ }
+
+ return model;
+ }
+
+ protected void findClassProperties(ProcessingEnvironment processingEnv, PrintWriter writer, RoundEnvironment roundEnv, Set<EipOption> eipOptions,
+ TypeElement originalClassType, TypeElement classElement, String prefix, String modelName) {
+ while (true) {
+ List<VariableElement> fieldElements = ElementFilter.fieldsIn(classElement.getEnclosedElements());
+ for (VariableElement fieldElement : fieldElements) {
+
+ String fieldName = fieldElement.getSimpleName().toString();
+
+ XmlAttribute attribute = fieldElement.getAnnotation(XmlAttribute.class);
+ if (attribute != null) {
+ boolean skip = processAttribute(processingEnv, roundEnv, originalClassType, classElement, fieldElement, fieldName, attribute, eipOptions, prefix, modelName);
+ if (skip) {
+ continue;
+ }
+ }
+
+ XmlValue value = fieldElement.getAnnotation(XmlValue.class);
+ if (value != null) {
+ processValue(processingEnv, roundEnv, originalClassType, classElement, fieldElement, fieldName, value, eipOptions, prefix, modelName);
+ }
+
+ XmlElements elements = fieldElement.getAnnotation(XmlElements.class);
+ if (elements != null) {
+ processElements(processingEnv, roundEnv, classElement, elements, fieldElement, eipOptions, prefix);
+ }
+
+ XmlElement element = fieldElement.getAnnotation(XmlElement.class);
+ if (element != null) {
+ processElement(processingEnv, roundEnv, classElement, element, fieldElement, eipOptions, prefix);
+ }
+
+ // special for eips which has outputs or requires an expressions
+ XmlElementRef elementRef = fieldElement.getAnnotation(XmlElementRef.class);
+ if (elementRef != null) {
+
+ // special for routes
+ processRoutes(roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
+
+ // special for outputs
+ processOutputs(processingEnv, roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
+
+ // special for when clauses (choice eip)
+ processRefWhenClauses(processingEnv, roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
+
+ // special for rests (rest-dsl)
+ processRests(roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
+
+ // special for verbs (rest-dsl)
+ processVerbs(processingEnv, roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
+
+ // special for expression
+ processRefExpression(processingEnv, roundEnv, originalClassType, classElement, elementRef, fieldElement, fieldName, eipOptions, prefix);
+
+ }
+ }
+
+ // special when we process these nodes as they do not use JAXB annotations on fields, but on methods
+ if ("OptionalIdentifiedDefinition".equals(classElement.getSimpleName().toString())) {
+ processIdentified(processingEnv, roundEnv, originalClassType, classElement, eipOptions, prefix);
+ } else if ("RouteDefinition".equals(classElement.getSimpleName().toString())) {
+ processRoute(processingEnv, roundEnv, originalClassType, classElement, eipOptions, prefix);
+ }
+
+ // check super classes which may also have fields
+ TypeElement baseTypeElement = null;
+ TypeMirror superclass = classElement.getSuperclass();
+ if (superclass != null) {
+ String superClassName = canonicalClassName(superclass.toString());
+ baseTypeElement = findTypeElement(processingEnv, roundEnv, superClassName);
+ }
+ if (baseTypeElement != null) {
+ classElement = baseTypeElement;
+ } else {
+ break;
+ }
+ }
+ }
+
+ private boolean processAttribute(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement, VariableElement fieldElement,
+ String fieldName, XmlAttribute attribute, Set<EipOption> eipOptions, String prefix, String modelName) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ String name = attribute.name();
+ if (isNullOrEmpty(name) || "##default".equals(name)) {
+ name = fieldName;
+ }
+
+ // lets skip some unwanted attributes
+ if (skipUnwanted) {
+ // we want to skip inheritErrorHandler which is only applicable for the load-balancer
+ boolean loadBalancer = "LoadBalanceDefinition".equals(originalClassType.getSimpleName().toString());
+ if (!loadBalancer && "inheritErrorHandler".equals(name)) {
+ return true;
+ }
+ }
+
+ name = prefix + name;
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+ TypeElement fieldTypeElement = findTypeElement(processingEnv, roundEnv, fieldTypeName);
+
+ String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
+ boolean required = attribute.required();
+ // metadata may overrule element required
+ required = findRequired(fieldElement, required);
+
+ // gather enums
+ Set<String> enums = new TreeSet<String>();
+ boolean isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
+ if (isEnum) {
+ TypeElement enumClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString());
+ // find all the enum constants which has the possible enum value that can be used
+ List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
+ for (VariableElement var : fields) {
+ if (var.getKind() == ElementKind.ENUM_CONSTANT) {
+ String val = var.toString();
+ enums.add(val);
+ }
+ }
+ }
+
+ boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
+
+ EipOption ep = new EipOption(name, "attribute", fieldTypeName, required, defaultValue, docComment, deprecated, isEnum, enums, false, null);
+ eipOptions.add(ep);
+
+ return false;
+ }
+
+ private void processValue(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement originalClassType,
+ TypeElement classElement, VariableElement fieldElement, String fieldName, XmlValue value,
+ Set<EipOption> eipOptions, String prefix, String modelName) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ // XmlValue has no name attribute
+ String name = fieldName;
+
+ if ("method".equals(modelName) || "tokenize".equals(modelName) || "xtokenize".equals(modelName)) {
+ // skip expression attribute on these three languages as they are solely configured using attributes
+ if ("expression".equals(name)) {
+ return;
+ }
+ }
+
+ name = prefix + name;
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
+ boolean required = true;
+ // metadata may overrule element required
+ required = findRequired(fieldElement, required);
+
+ boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
+
+ EipOption ep = new EipOption(name, "value", fieldTypeName, required, defaultValue, docComment, deprecated, false, null, false, null);
+ eipOptions.add(ep);
+ }
+
+ private void processElement(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement classElement, XmlElement element, VariableElement fieldElement,
+ Set<EipOption> eipOptions, String prefix) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ String fieldName;
+ fieldName = fieldElement.getSimpleName().toString();
+ if (element != null) {
+
+ String kind = "element";
+ String name = element.name();
+ if (isNullOrEmpty(name) || "##default".equals(name)) {
+ name = fieldName;
+ }
+ name = prefix + name;
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+ TypeElement fieldTypeElement = findTypeElement(processingEnv, roundEnv, fieldTypeName);
+
+ String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
+ boolean required = element.required();
+ // metadata may overrule element required
+ required = findRequired(fieldElement, required);
+
+ // gather enums
+ Set<String> enums = new LinkedHashSet<String>();
+ boolean isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
+ if (isEnum) {
+ TypeElement enumClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString());
+ // find all the enum constants which has the possible enum value that can be used
+ List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
+ for (VariableElement var : fields) {
+ if (var.getKind() == ElementKind.ENUM_CONSTANT) {
+ String val = var.toString();
+ enums.add(val);
+ }
+ }
+ }
+
+ // gather oneOf expression/predicates which uses language
+ Set<String> oneOfTypes = new TreeSet<String>();
+ boolean isOneOf = ONE_OF_TYPE_NAME.equals(fieldTypeName);
+ if (isOneOf) {
+ // okay its actually an language expression, so favor using that in the eip option
+ kind = "expression";
+ for (String language : ONE_OF_LANGUAGES) {
+ fieldTypeName = language;
+ TypeElement languages = findTypeElement(processingEnv, roundEnv, language);
+ String superClassName = canonicalClassName(languages.toString());
+ // find all classes that has that superClassName
+ Set<TypeElement> children = new LinkedHashSet<TypeElement>();
+ findTypeElementChildren(processingEnv, 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);
+ }
+ }
+ }
+ }
+ }
+ // special for otherwise as we want to indicate that the element is
+ if ("otherwise".equals(name)) {
+ isOneOf = true;
+ oneOfTypes.add("otherwise");
+ }
+
+ boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
+
+ EipOption ep = new EipOption(name, kind, fieldTypeName, required, defaultValue, docComment, deprecated, isEnum, enums, isOneOf, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ private void processElements(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement classElement, XmlElements elements, VariableElement fieldElement,
+ Set<EipOption> eipOptions, String prefix) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ String fieldName;
+ fieldName = fieldElement.getSimpleName().toString();
+ if (elements != null) {
+ String kind = "element";
+ String name = fieldName;
+ name = prefix + name;
+
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
+
+ boolean required = true;
+ required = findRequired(fieldElement, required);
+
+ // gather oneOf of the elements
+ Set<String> oneOfTypes = new TreeSet<String>();
+ for (XmlElement element : elements.value()) {
+ String child = element.name();
+ oneOfTypes.add(child);
+ }
+
+ EipOption ep = new EipOption(name, kind, fieldTypeName, required, defaultValue, docComment, false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ private void processRoute(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement,
+ Set<EipOption> eipOptions, String prefix) {
+
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ // group
+ String docComment = findJavaDoc(elementUtils, null, "group", null, classElement, true);
+ EipOption ep = new EipOption("group", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // group
+ docComment = findJavaDoc(elementUtils, null, "streamCache", null, classElement, true);
+ ep = new EipOption("streamCache", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // trace
+ docComment = findJavaDoc(elementUtils, null, "trace", null, classElement, true);
+ ep = new EipOption("trace", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // trace
+ docComment = findJavaDoc(elementUtils, null, "messageHistory", null, classElement, true);
+ ep = new EipOption("messageHistory", "attribute", "java.lang.String", false, "true", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // trace
+ docComment = findJavaDoc(elementUtils, null, "handleFault", null, classElement, true);
+ ep = new EipOption("handleFault", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // delayer
+ docComment = findJavaDoc(elementUtils, null, "delayer", null, classElement, true);
+ ep = new EipOption("delayer", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // autoStartup
+ docComment = findJavaDoc(elementUtils, null, "autoStartup", null, classElement, true);
+ ep = new EipOption("autoStartup", "attribute", "java.lang.String", false, "true", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // startupOrder
+ docComment = findJavaDoc(elementUtils, null, "startupOrder", null, classElement, true);
+ ep = new EipOption("startupOrder", "attribute", "java.lang.Integer", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // errorHandlerRef
+ docComment = findJavaDoc(elementUtils, null, "errorHandlerRef", null, classElement, true);
+ ep = new EipOption("errorHandlerRef", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // routePolicyRef
+ docComment = findJavaDoc(elementUtils, null, "routePolicyRef", null, classElement, true);
+ ep = new EipOption("routePolicyRef", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // shutdownRoute
+ Set<String> enums = new LinkedHashSet<String>();
+ enums.add("Default");
+ enums.add("Defer");
+ docComment = findJavaDoc(elementUtils, null, "shutdownRoute", "Default", classElement, true);
+ ep = new EipOption("shutdownRoute", "attribute", "org.apache.camel.ShutdownRoute", false, "", docComment, false, true, enums, false, null);
+ eipOptions.add(ep);
+
+ // shutdownRunningTask
+ enums = new LinkedHashSet<String>();
+ enums.add("CompleteCurrentTaskOnly");
+ enums.add("CompleteAllTasks");
+ docComment = findJavaDoc(elementUtils, null, "shutdownRunningTask", "CompleteCurrentTaskOnly", classElement, true);
+ ep = new EipOption("shutdownRunningTask", "attribute", "org.apache.camel.ShutdownRunningTask", false, "", docComment, false, true, enums, false, null);
+ eipOptions.add(ep);
+
+ // inputs
+ Set<String> oneOfTypes = new TreeSet<String>();
+ oneOfTypes.add("from");
+ docComment = findJavaDoc(elementUtils, null, "inputs", null, classElement, true);
+ ep = new EipOption("inputs", "element", "java.util.List<org.apache.camel.model.FromDefinition>", true, "", docComment, false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+
+ // outputs
+ // gather oneOf which extends any of the output base classes
+ oneOfTypes = new TreeSet<String>();
+ // find all classes that has that superClassName
+ Set<TypeElement> children = new LinkedHashSet<TypeElement>();
+ for (String superclass : ONE_OF_OUTPUTS) {
+ findTypeElementChildren(processingEnv, roundEnv, children, superclass);
+ }
+ for (TypeElement child : children) {
+ XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class);
+ if (rootElement != null) {
+ String childName = rootElement.name();
+ if (childName != null) {
+ oneOfTypes.add(childName);
+ }
+ }
+ }
+
+ // remove some types which are not intended as an output in eips
+ oneOfTypes.remove("route");
+
+ docComment = findJavaDoc(elementUtils, null, "outputs", null, classElement, true);
+ ep = new EipOption("outputs", "element", "java.util.List<org.apache.camel.model.ProcessorDefinition<?>>", true, "", docComment, false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+
+ /**
+ * Special for process the OptionalIdentifiedDefinition
+ */
+ private void processIdentified(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement,
+ Set<EipOption> eipOptions, String prefix) {
+
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ // id
+ String docComment = findJavaDoc(elementUtils, null, "id", null, classElement, true);
+ EipOption ep = new EipOption("id", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // description
+ docComment = findJavaDoc(elementUtils, null, "description", null, classElement, true);
+ ep = new EipOption("description", "element", "org.apache.camel.model.DescriptionDefinition", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+
+ // lets skip custom id as it has no value for end users to configure
+ if (!skipUnwanted) {
+ // custom id
+ docComment = findJavaDoc(elementUtils, null, "customId", null, classElement, true);
+ ep = new EipOption("customId", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
+ eipOptions.add(ep);
+ }
+ }
+
+ /**
+ * Special for processing an @XmlElementRef routes field
+ */
+ private void processRoutes(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
+ VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
+ if ("routes".equals(fieldName)) {
+
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ Set<String> oneOfTypes = new TreeSet<String>();
+ oneOfTypes.add("route");
+
+ EipOption ep = new EipOption("routes", "element", fieldTypeName, false, "", "Contains the Camel routes", false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ /**
+ * Special for processing an @XmlElementRef rests field
+ */
+ private void processRests(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
+ VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
+ if ("rests".equals(fieldName)) {
+
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ Set<String> oneOfTypes = new TreeSet<String>();
+ oneOfTypes.add("rest");
+
+ EipOption ep = new EipOption("rests", "element", fieldTypeName, false, "", "Contains the rest services defined using the rest-dsl", false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ /**
+ * Special for processing an @XmlElementRef outputs field
+ */
+ private void processOutputs(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
+ VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
+ if ("outputs".equals(fieldName) && supportOutputs(originalClassType)) {
+ String kind = "element";
+ String name = elementRef.name();
+ if (isNullOrEmpty(name) || "##default".equals(name)) {
+ name = fieldName;
+ }
+ name = prefix + name;
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ // gather oneOf which extends any of the output base classes
+ Set<String> oneOfTypes = new TreeSet<String>();
+ // find all classes that has that superClassName
+ Set<TypeElement> children = new LinkedHashSet<TypeElement>();
+ for (String superclass : ONE_OF_OUTPUTS) {
+ findTypeElementChildren(processingEnv, roundEnv, children, superclass);
+ }
+ for (TypeElement child : children) {
+ XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class);
+ if (rootElement != null) {
+ String childName = rootElement.name();
+ if (childName != null) {
+ oneOfTypes.add(childName);
+ }
+ }
+ }
+
+ // remove some types which are not intended as an output in eips
+ oneOfTypes.remove("route");
+
+ EipOption ep = new EipOption(name, kind, fieldTypeName, true, "", "", false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ /**
+ * Special for processing an @XmlElementRef verbs field (rest-dsl)
+ */
+ private void processVerbs(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
+ VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
+
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ if ("verbs".equals(fieldName) && supportOutputs(originalClassType)) {
+ String kind = "element";
+ String name = elementRef.name();
+ if (isNullOrEmpty(name) || "##default".equals(name)) {
+ name = fieldName;
+ }
+ name = prefix + name;
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, originalClassType, true);
+
+ // gather oneOf which extends any of the output base classes
+ Set<String> oneOfTypes = new TreeSet<String>();
+ // find all classes that has that superClassName
+ Set<TypeElement> children = new LinkedHashSet<TypeElement>();
+ for (String superclass : ONE_OF_VERBS) {
+ findTypeElementChildren(processingEnv, roundEnv, children, superclass);
+ }
+ 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, true, "", docComment, false, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ /**
+ * Special for processing an @XmlElementRef expression field
+ */
+ private void processRefExpression(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement,
+ XmlElementRef elementRef, VariableElement fieldElement,
+ String fieldName, Set<EipOption> eipOptions, String prefix) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ if ("expression".equals(fieldName)) {
+ String kind = "expression";
+ String name = elementRef.name();
+ if (isNullOrEmpty(name) || "##default".equals(name)) {
+ name = fieldName;
+ }
+ name = prefix + name;
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ // find javadoc from original class as it will override the setExpression method where we can provide the javadoc for the given EIP
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, originalClassType, true);
+
+ // gather oneOf expression/predicates which uses language
+ Set<String> oneOfTypes = new TreeSet<String>();
+ for (String language : ONE_OF_LANGUAGES) {
+ TypeElement languages = findTypeElement(processingEnv, roundEnv, language);
+ String superClassName = canonicalClassName(languages.toString());
+ // find all classes that has that superClassName
+ Set<TypeElement> children = new LinkedHashSet<TypeElement>();
+ findTypeElementChildren(processingEnv, 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);
+ }
+ }
+ }
+ }
+
+ boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
+
+ EipOption ep = new EipOption(name, kind, fieldTypeName, true, "", docComment, deprecated, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ /**
+ * Special for processing an @XmlElementRef when field
+ */
+ private void processRefWhenClauses(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
+ VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ if ("whenClauses".equals(fieldName)) {
+ String kind = "element";
+ String name = elementRef.name();
+ if (isNullOrEmpty(name) || "##default".equals(name)) {
+ name = fieldName;
+ }
+ name = prefix + name;
+ TypeMirror fieldType = fieldElement.asType();
+ String fieldTypeName = fieldType.toString();
+
+ // find javadoc from original class as it will override the setExpression method where we can provide the javadoc for the given EIP
+ String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, originalClassType, true);
+ boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
+
+ // indicate that this element is one of when
+ Set<String> oneOfTypes = new HashSet<String>();
+ oneOfTypes.add("when");
+
+ EipOption ep = new EipOption(name, kind, fieldTypeName, false, "", docComment, deprecated, false, null, true, oneOfTypes);
+ eipOptions.add(ep);
+ }
+ }
+
+ /**
+ * Whether the class supports outputs.
+ * <p/>
+ * There are some classes which does not support outputs, even though they have a outputs element.
+ */
+ private boolean supportOutputs(TypeElement classElement) {
+ String superclass = canonicalClassName(classElement.getSuperclass().toString());
+ return !"org.apache.camel.model.NoOutputExpressionNode".equals(superclass);
+ }
+
+ private String findDefaultValue(VariableElement fieldElement, String fieldTypeName) {
+ String defaultValue = null;
+ Metadata metadata = fieldElement.getAnnotation(Metadata.class);
+ if (metadata != null) {
+ if (!Strings.isNullOrEmpty(metadata.defaultValue())) {
+ defaultValue = metadata.defaultValue();
+ }
+ }
+ if (defaultValue == null) {
+ // if its a boolean type, then we use false as the default
+ if ("boolean".equals(fieldTypeName) || "java.lang.Boolean".equals(fieldTypeName)) {
+ defaultValue = "false";
+ }
+ }
+
+ return defaultValue;
+ }
+
+ private boolean findRequired(VariableElement fieldElement, boolean defaultValue) {
+ Metadata metadata = fieldElement.getAnnotation(Metadata.class);
+ if (metadata != null) {
+ if (!Strings.isNullOrEmpty(metadata.required())) {
+ defaultValue = "true".equals(metadata.required());
+ }
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Capitializes the name as a title
+ *
+ * @param name the name
+ * @return as a title
+ */
+ private static String asTitle(String name) {
+ StringBuilder sb = new StringBuilder();
+ for (char c : name.toCharArray()) {
+ boolean upper = Character.isUpperCase(c);
+ boolean first = sb.length() == 0;
+ if (first) {
+ sb.append(Character.toUpperCase(c));
+ } else if (upper) {
+ sb.append(' ');
+ sb.append(c);
+ } else {
+ sb.append(Character.toLowerCase(c));
+ }
+ }
+ return sb.toString().trim();
+ }
+
+ private boolean hasInput(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement classElement) {
+ for (String name : ONE_OF_INPUTS) {
+ if (hasSuperClass(processingEnv, roundEnv, classElement, name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean hasOutput(EipModel model, Set<EipOption> options) {
+ // if we are route/rest then we accept output
+ if ("route".equals(model.getName()) || "rest".equals(model.getName())) {
+ return true;
+ }
+
+ for (EipOption option : options) {
+ if ("outputs".equals(option.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static final class EipModel {
+
+ private String name;
+ private String title;
+ private String javaType;
+ private String label;
+ private String description;
+ private boolean input;
+ private boolean output;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getJavaType() {
+ return javaType;
+ }
+
+ public void setJavaType(String javaType) {
+ this.javaType = javaType;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public boolean isInput() {
+ return input;
+ }
+
+ public void setInput(boolean input) {
+ this.input = input;
+ }
+
+ public String getInput() {
+ return input ? "true" : "false";
+ }
+
+ public boolean isOutput() {
+ return output;
+ }
+
+ public void setOutput(boolean output) {
+ this.output = output;
+ }
+
+ public String getOutput() {
+ return output ? "true" : "false";
+ }
+
+ }
+
+ private static final class EipOption {
+
+ private String name;
+ private String kind;
+ private String type;
+ private boolean required;
+ private String defaultValue;
+ private String documentation;
+ private boolean deprecated;
+ 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 documentation, boolean deprecated,
+ boolean enumType, Set<String> enums, boolean oneOf, Set<String> oneOfTypes) {
+ this.name = name;
+ this.kind = kind;
+ this.type = type;
+ this.required = required;
+ this.defaultValue = defaultValue;
+ this.documentation = documentation;
+ this.deprecated = deprecated;
+ this.enumType = enumType;
+ this.enums = enums;
+ this.oneOf = oneOf;
+ this.oneOfTypes = oneOfTypes;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getKind() {
+ return kind;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ public String getDocumentation() {
+ return documentation;
+ }
+
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
+ public boolean isEnumType() {
+ return enumType;
+ }
+
+ public Set<String> getEnums() {
+ return enums;
+ }
+
+ public boolean isOneOf() {
+ return oneOf;
+ }
+
+ public Set<String> getOneOfTypes() {
+ return oneOfTypes;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ EipOption that = (EipOption) o;
+
+ if (!name.equals(that.name)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+ }
+
+ private static final class EipOptionComparator implements Comparator<EipOption> {
+
+ private final EipModel model;
+
+ private EipOptionComparator(EipModel model) {
+ this.model = model;
+ }
+
+ @Override
+ public int compare(EipOption o1, EipOption o2) {
+ int weigth = weigth(o1);
+ int weigth2 = weigth(o2);
+
+ if (weigth == weigth2) {
+ // keep the current order
+ return 1;
+ } else {
+ // sort according to weight
+ return weigth2 - weigth;
+ }
+ }
+
+ private int weigth(EipOption o) {
+ String name = o.getName();
+
+ // these should be first
+ if ("expression".equals(name)) {
+ return 10;
+ }
+
+ // these should be last
+ if ("description".equals(name)) {
+ return -10;
+ } else if ("id".equals(name)) {
+ return -9;
+ } else if ("pattern".equals(name) && "to".equals(model.getName())) {
+ // and pattern only for the to model
+ return -8;
+ }
+ return 0;
+ }
+ }
+
+}
[4/4] camel git commit: CAMEL-9482: Adjust the apt to make camel-core
compile again,
seems like we need to merge the core/spring into a single apt as the compiler
cannot do both on camel-core for some odd reason.
Posted by da...@apache.org.
CAMEL-9482: Adjust the apt to make camel-core compile again, seems like we need to merge the core/spring into a single apt as the compiler cannot do both on camel-core for some odd reason.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/8a18e284
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/8a18e284
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/8a18e284
Branch: refs/heads/master
Commit: 8a18e2849b08898d51b84c59fd892691ac593a94
Parents: bbb7ff9
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Aug 11 09:41:27 2016 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Aug 11 09:43:41 2016 +0200
----------------------------------------------------------------------
.../tools/apt/AbstractAnnotationProcessor.java | 419 -------
.../tools/apt/AnnotationProcessorHelper.java | 421 +++++++
.../apt/CamelContextAnnotationProcessor.java | 720 -----------
.../tools/apt/CoreEipAnnotationProcessor.java | 1127 +++++++++++++++++
.../camel/tools/apt/EipAnnotationProcessor.java | 1148 ------------------
.../tools/apt/EndpointAnnotationProcessor.java | 45 +-
.../tools/apt/ModelAnnotationProcessor.java | 71 ++
.../tools/apt/SpringAnnotationProcessor.java | 689 +++++++++++
.../javax.annotation.processing.Processor | 5 +-
9 files changed, 2338 insertions(+), 2307 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/8a18e284/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
deleted file mode 100644
index 6159602..0000000
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/AbstractAnnotationProcessor.java
+++ /dev/null
@@ -1,419 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.tools.apt;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.net.URI;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Filer;
-import javax.annotation.processing.RoundEnvironment;
-import javax.lang.model.element.Element;
-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.DeclaredType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-import javax.lang.model.util.Elements;
-import javax.tools.Diagnostic;
-import javax.tools.FileObject;
-import javax.tools.StandardLocation;
-
-import static org.apache.camel.tools.apt.helper.IOHelper.loadText;
-import static org.apache.camel.tools.apt.helper.Strings.canonicalClassName;
-import static org.apache.camel.tools.apt.helper.Strings.isNullOrEmpty;
-
-/**
- * Abstract class for Camel apt plugins.
- */
-public abstract class AbstractAnnotationProcessor extends AbstractProcessor {
-
- protected String findJavaDoc(Elements elementUtils, Element element, String fieldName, String name, TypeElement classElement, boolean builderPattern) {
- String answer = null;
- if (element != null) {
- answer = elementUtils.getDocComment(element);
- }
- if (isNullOrEmpty(answer)) {
- ExecutableElement setter = findSetter(fieldName, classElement);
- if (setter != null) {
- String doc = elementUtils.getDocComment(setter);
- if (!isNullOrEmpty(doc)) {
- answer = doc;
- }
- }
-
- // lets find the getter
- if (answer == null) {
- ExecutableElement getter = findGetter(fieldName, classElement);
- if (getter != null) {
- String doc = elementUtils.getDocComment(getter);
- if (!isNullOrEmpty(doc)) {
- answer = doc;
- }
- }
- }
-
- // lets try builder pattern
- if (answer == null && builderPattern) {
- List<ExecutableElement> methods = ElementFilter.methodsIn(classElement.getEnclosedElements());
- // lets try the builder pattern using annotation name (optional) as the method name
- if (name != null) {
- for (ExecutableElement method : methods) {
- String methodName = method.getSimpleName().toString();
- if (name.equals(methodName) && method.getParameters().size() == 1) {
- String doc = elementUtils.getDocComment(method);
- if (!isNullOrEmpty(doc)) {
- answer = doc;
- break;
- }
- }
- }
- // there may be builder pattern with no-parameter methods, such as more common for boolean types
- // so lets try those as well
- for (ExecutableElement method : methods) {
- String methodName = method.getSimpleName().toString();
- if (name.equals(methodName) && method.getParameters().size() == 0) {
- String doc = elementUtils.getDocComment(method);
- if (!isNullOrEmpty(doc)) {
- answer = doc;
- break;
- }
- }
- }
- }
- // lets try builder pattern using fieldName as the method name
- 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;
- }
- }
- }
- // there may be builder pattern with no-parameter methods, such as more common for boolean types
- // so lets try those as well
- for (ExecutableElement method : methods) {
- String methodName = method.getSimpleName().toString();
- if (fieldName.equals(methodName) && method.getParameters().size() == 0) {
- String doc = elementUtils.getDocComment(method);
- if (!isNullOrEmpty(doc)) {
- answer = doc;
- break;
- }
- }
- }
- }
- }
- return answer;
- }
-
- protected ExecutableElement findSetter(String fieldName, TypeElement classElement) {
- String setter = "set" + fieldName.substring(0, 1).toUpperCase();
- if (fieldName.length() > 1) {
- setter += fieldName.substring(1);
- }
- // lets find the setter
- List<ExecutableElement> methods = ElementFilter.methodsIn(classElement.getEnclosedElements());
- for (ExecutableElement method : methods) {
- String methodName = method.getSimpleName().toString();
- if (setter.equals(methodName) && method.getParameters().size() == 1 && method.getReturnType().getKind().equals(TypeKind.VOID)) {
- return method;
- }
- }
-
- return null;
- }
-
- protected ExecutableElement findGetter(String fieldName, TypeElement classElement) {
- String getter1 = "get" + fieldName.substring(0, 1).toUpperCase();
- if (fieldName.length() > 1) {
- getter1 += fieldName.substring(1);
- }
- String getter2 = "is" + fieldName.substring(0, 1).toUpperCase();
- if (fieldName.length() > 1) {
- getter2 += fieldName.substring(1);
- }
- // lets find the getter
- List<ExecutableElement> methods = ElementFilter.methodsIn(classElement.getEnclosedElements());
- for (ExecutableElement method : methods) {
- String methodName = method.getSimpleName().toString();
- if ((getter1.equals(methodName) || getter2.equals(methodName)) && method.getParameters().size() == 0) {
- return method;
- }
- }
-
- return null;
- }
-
- protected VariableElement findFieldElement(TypeElement classElement, String fieldName) {
- if (isNullOrEmpty(fieldName)) {
- return null;
- }
-
- List<VariableElement> fields = ElementFilter.fieldsIn(classElement.getEnclosedElements());
- for (VariableElement field : fields) {
- if (fieldName.equals(field.getSimpleName().toString())) {
- return field;
- }
- }
-
- return null;
- }
-
- protected TypeElement findTypeElement(RoundEnvironment roundEnv, String className) {
- if (isNullOrEmpty(className) || "java.lang.Object".equals(className)) {
- return null;
- }
-
- Set<? extends Element> rootElements = roundEnv.getRootElements();
- for (Element rootElement : rootElements) {
- if (rootElement instanceof TypeElement) {
- TypeElement typeElement = (TypeElement) rootElement;
- String aRootName = canonicalClassName(typeElement.getQualifiedName().toString());
- if (className.equals(aRootName)) {
- return typeElement;
- }
- }
- }
-
- // fallback using package name
- Elements elementUtils = processingEnv.getElementUtils();
-
- int idx = className.lastIndexOf('.');
- if (idx > 0) {
- String packageName = className.substring(0, idx);
- PackageElement pe = elementUtils.getPackageElement(packageName);
- if (pe != null) {
- List<? extends Element> enclosedElements = getEnclosedElements(pe);
- for (Element rootElement : enclosedElements) {
- if (rootElement instanceof TypeElement) {
- TypeElement typeElement = (TypeElement) rootElement;
- String aRootName = canonicalClassName(typeElement.getQualifiedName().toString());
- if (className.equals(aRootName)) {
- return typeElement;
- }
- }
- }
- }
- }
-
- return null;
- }
-
- @SuppressWarnings("unchecked")
- private List<? extends Element> getEnclosedElements(PackageElement pe) {
- // some components like hadoop/spark has bad classes that causes javac scanning issues
- try {
- return pe.getEnclosedElements();
- } catch (Throwable e) {
- // ignore
- }
- return Collections.EMPTY_LIST;
- }
-
- 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);
- }
- }
- }
- }
- }
- }
-
- protected boolean hasSuperClass(RoundEnvironment roundEnv, TypeElement classElement, String superClassName) {
- String aRootName = canonicalClassName(classElement.getQualifiedName().toString());
-
- // do not check the classes from JDK itself
- if (isNullOrEmpty(aRootName) || aRootName.startsWith("java.") || aRootName.startsWith("javax.")) {
- return false;
- }
-
- String aSuperClassName = canonicalClassName(classElement.getSuperclass().toString());
- if (superClassName.equals(aSuperClassName)) {
- return true;
- }
-
- TypeElement aSuperClass = findTypeElement(roundEnv, aSuperClassName);
- if (aSuperClass != null) {
- return hasSuperClass(roundEnv, aSuperClass, superClassName);
- } else {
- return false;
- }
- }
-
- protected boolean implementsInterface(RoundEnvironment roundEnv, TypeElement classElement, String interfaceClassName) {
- while (true) {
- // check if the class implements the interface
- List<? extends TypeMirror> list = classElement.getInterfaces();
- if (list != null) {
- for (TypeMirror type : list) {
- if (type.getKind().compareTo(TypeKind.DECLARED) == 0) {
- String name = type.toString();
- if (interfaceClassName.equals(name)) {
- return true;
- }
- }
- }
- }
-
- // check super classes which may implement the interface
- TypeElement baseTypeElement = null;
- TypeMirror superclass = classElement.getSuperclass();
- if (superclass != null) {
- String superClassName = canonicalClassName(superclass.toString());
- baseTypeElement = findTypeElement(roundEnv, superClassName);
- }
- if (baseTypeElement != null) {
- classElement = baseTypeElement;
- } else {
- break;
- }
- }
-
- return false;
- }
-
- /**
- * Helper method to produce class output text file using the given handler
- */
- protected void processFile(String packageName, String fileName, Func1<PrintWriter, Void> handler) {
- PrintWriter writer = null;
- try {
- Writer out;
- Filer filer = processingEnv.getFiler();
- FileObject resource;
- try {
- resource = filer.getResource(StandardLocation.CLASS_OUTPUT, packageName, fileName);
- } catch (Throwable e) {
- resource = filer.createResource(StandardLocation.CLASS_OUTPUT, packageName, fileName);
- }
- URI uri = resource.toUri();
- File file = null;
- if (uri != null) {
- try {
- file = new File(uri.getPath());
- } catch (Exception e) {
- warning("Could not convert output directory resource URI to a file " + e);
- }
- }
- if (file == null) {
- warning("No class output directory could be found!");
- } else {
- file.getParentFile().mkdirs();
- out = new FileWriter(file);
- writer = new PrintWriter(out);
- handler.call(writer);
- }
- } catch (IOException e) {
- log(e);
- } finally {
- if (writer != null) {
- writer.close();
- }
- }
- }
-
- protected void log(String message) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message);
- }
-
- protected void warning(String message) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, message);
- }
-
- protected void error(String message) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message);
- }
-
- protected void log(Throwable e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
- StringWriter buffer = new StringWriter();
- PrintWriter writer = new PrintWriter(buffer);
- e.printStackTrace(writer);
- writer.close();
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, buffer.toString());
- }
-
- protected String loadResource(String packageName, String fileName) {
- Filer filer = processingEnv.getFiler();
-
- FileObject resource;
- try {
- resource = filer.getResource(StandardLocation.CLASS_OUTPUT, "", packageName + "/" + fileName);
- } catch (Throwable e) {
- return "Crap" + e.getMessage();
- }
-
- if (resource == null) {
- return null;
- }
-
- try {
- InputStream is = resource.openInputStream();
- return loadText(is, true);
- } catch (Exception e) {
- warning("Could not load file");
- }
-
- return null;
- }
-
- protected void dumpExceptionToErrorFile(String fileName, String message, Throwable e) {
- File file = new File(fileName);
- try {
- FileOutputStream fos = new FileOutputStream(file);
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- e.printStackTrace(pw);
- fos.write(message.getBytes());
- fos.write("\n\n".getBytes());
- fos.write(sw.toString().getBytes());
- pw.close();
- sw.close();
- fos.close();
- } catch (Throwable t) {
- // ignore
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/8a18e284/tooling/apt/src/main/java/org/apache/camel/tools/apt/AnnotationProcessorHelper.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/AnnotationProcessorHelper.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/AnnotationProcessorHelper.java
new file mode 100644
index 0000000..ccbe807
--- /dev/null
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/AnnotationProcessorHelper.java
@@ -0,0 +1,421 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.tools.apt;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.Element;
+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.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.Elements;
+import javax.tools.Diagnostic;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+
+import static org.apache.camel.tools.apt.helper.IOHelper.loadText;
+import static org.apache.camel.tools.apt.helper.Strings.canonicalClassName;
+import static org.apache.camel.tools.apt.helper.Strings.isNullOrEmpty;
+
+/**
+ * Abstract class for Camel apt plugins.
+ */
+public final class AnnotationProcessorHelper {
+
+ private AnnotationProcessorHelper() {
+ }
+
+ public static String findJavaDoc(Elements elementUtils, Element element, String fieldName, String name, TypeElement classElement, boolean builderPattern) {
+ String answer = null;
+ if (element != null) {
+ answer = elementUtils.getDocComment(element);
+ }
+ if (isNullOrEmpty(answer)) {
+ ExecutableElement setter = findSetter(fieldName, classElement);
+ if (setter != null) {
+ String doc = elementUtils.getDocComment(setter);
+ if (!isNullOrEmpty(doc)) {
+ answer = doc;
+ }
+ }
+
+ // lets find the getter
+ if (answer == null) {
+ ExecutableElement getter = findGetter(fieldName, classElement);
+ if (getter != null) {
+ String doc = elementUtils.getDocComment(getter);
+ if (!isNullOrEmpty(doc)) {
+ answer = doc;
+ }
+ }
+ }
+
+ // lets try builder pattern
+ if (answer == null && builderPattern) {
+ List<ExecutableElement> methods = ElementFilter.methodsIn(classElement.getEnclosedElements());
+ // lets try the builder pattern using annotation name (optional) as the method name
+ if (name != null) {
+ for (ExecutableElement method : methods) {
+ String methodName = method.getSimpleName().toString();
+ if (name.equals(methodName) && method.getParameters().size() == 1) {
+ String doc = elementUtils.getDocComment(method);
+ if (!isNullOrEmpty(doc)) {
+ answer = doc;
+ break;
+ }
+ }
+ }
+ // there may be builder pattern with no-parameter methods, such as more common for boolean types
+ // so lets try those as well
+ for (ExecutableElement method : methods) {
+ String methodName = method.getSimpleName().toString();
+ if (name.equals(methodName) && method.getParameters().size() == 0) {
+ String doc = elementUtils.getDocComment(method);
+ if (!isNullOrEmpty(doc)) {
+ answer = doc;
+ break;
+ }
+ }
+ }
+ }
+ // lets try builder pattern using fieldName as the method name
+ 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;
+ }
+ }
+ }
+ // there may be builder pattern with no-parameter methods, such as more common for boolean types
+ // so lets try those as well
+ for (ExecutableElement method : methods) {
+ String methodName = method.getSimpleName().toString();
+ if (fieldName.equals(methodName) && method.getParameters().size() == 0) {
+ String doc = elementUtils.getDocComment(method);
+ if (!isNullOrEmpty(doc)) {
+ answer = doc;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return answer;
+ }
+
+ public static ExecutableElement findSetter(String fieldName, TypeElement classElement) {
+ String setter = "set" + fieldName.substring(0, 1).toUpperCase();
+ if (fieldName.length() > 1) {
+ setter += fieldName.substring(1);
+ }
+ // lets find the setter
+ List<ExecutableElement> methods = ElementFilter.methodsIn(classElement.getEnclosedElements());
+ for (ExecutableElement method : methods) {
+ String methodName = method.getSimpleName().toString();
+ if (setter.equals(methodName) && method.getParameters().size() == 1 && method.getReturnType().getKind().equals(TypeKind.VOID)) {
+ return method;
+ }
+ }
+
+ return null;
+ }
+
+ public static ExecutableElement findGetter(String fieldName, TypeElement classElement) {
+ String getter1 = "get" + fieldName.substring(0, 1).toUpperCase();
+ if (fieldName.length() > 1) {
+ getter1 += fieldName.substring(1);
+ }
+ String getter2 = "is" + fieldName.substring(0, 1).toUpperCase();
+ if (fieldName.length() > 1) {
+ getter2 += fieldName.substring(1);
+ }
+ // lets find the getter
+ List<ExecutableElement> methods = ElementFilter.methodsIn(classElement.getEnclosedElements());
+ for (ExecutableElement method : methods) {
+ String methodName = method.getSimpleName().toString();
+ if ((getter1.equals(methodName) || getter2.equals(methodName)) && method.getParameters().size() == 0) {
+ return method;
+ }
+ }
+
+ return null;
+ }
+
+ public static VariableElement findFieldElement(TypeElement classElement, String fieldName) {
+ if (isNullOrEmpty(fieldName)) {
+ return null;
+ }
+
+ List<VariableElement> fields = ElementFilter.fieldsIn(classElement.getEnclosedElements());
+ for (VariableElement field : fields) {
+ if (fieldName.equals(field.getSimpleName().toString())) {
+ return field;
+ }
+ }
+
+ return null;
+ }
+
+ public static TypeElement findTypeElement(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, String className) {
+ if (isNullOrEmpty(className) || "java.lang.Object".equals(className)) {
+ return null;
+ }
+
+ Set<? extends Element> rootElements = roundEnv.getRootElements();
+ for (Element rootElement : rootElements) {
+ if (rootElement instanceof TypeElement) {
+ TypeElement typeElement = (TypeElement) rootElement;
+ String aRootName = canonicalClassName(typeElement.getQualifiedName().toString());
+ if (className.equals(aRootName)) {
+ return typeElement;
+ }
+ }
+ }
+
+ // fallback using package name
+ Elements elementUtils = processingEnv.getElementUtils();
+
+ int idx = className.lastIndexOf('.');
+ if (idx > 0) {
+ String packageName = className.substring(0, idx);
+ PackageElement pe = elementUtils.getPackageElement(packageName);
+ if (pe != null) {
+ List<? extends Element> enclosedElements = getEnclosedElements(pe);
+ for (Element rootElement : enclosedElements) {
+ if (rootElement instanceof TypeElement) {
+ TypeElement typeElement = (TypeElement) rootElement;
+ String aRootName = canonicalClassName(typeElement.getQualifiedName().toString());
+ if (className.equals(aRootName)) {
+ return typeElement;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static List<? extends Element> getEnclosedElements(PackageElement pe) {
+ // some components like hadoop/spark has bad classes that causes javac scanning issues
+ try {
+ return pe.getEnclosedElements();
+ } catch (Throwable e) {
+ // ignore
+ }
+ return Collections.EMPTY_LIST;
+ }
+
+ public static void findTypeElementChildren(ProcessingEnvironment processingEnv, 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);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static boolean hasSuperClass(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement classElement, String superClassName) {
+ String aRootName = canonicalClassName(classElement.getQualifiedName().toString());
+
+ // do not check the classes from JDK itself
+ if (isNullOrEmpty(aRootName) || aRootName.startsWith("java.") || aRootName.startsWith("javax.")) {
+ return false;
+ }
+
+ String aSuperClassName = canonicalClassName(classElement.getSuperclass().toString());
+ if (superClassName.equals(aSuperClassName)) {
+ return true;
+ }
+
+ TypeElement aSuperClass = findTypeElement(processingEnv, roundEnv, aSuperClassName);
+ if (aSuperClass != null) {
+ return hasSuperClass(processingEnv, roundEnv, aSuperClass, superClassName);
+ } else {
+ return false;
+ }
+ }
+
+ public static boolean implementsInterface(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement classElement, String interfaceClassName) {
+ while (true) {
+ // check if the class implements the interface
+ List<? extends TypeMirror> list = classElement.getInterfaces();
+ if (list != null) {
+ for (TypeMirror type : list) {
+ if (type.getKind().compareTo(TypeKind.DECLARED) == 0) {
+ String name = type.toString();
+ if (interfaceClassName.equals(name)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ // check super classes which may implement the interface
+ TypeElement baseTypeElement = null;
+ TypeMirror superclass = classElement.getSuperclass();
+ if (superclass != null) {
+ String superClassName = canonicalClassName(superclass.toString());
+ baseTypeElement = findTypeElement(processingEnv, roundEnv, superClassName);
+ }
+ if (baseTypeElement != null) {
+ classElement = baseTypeElement;
+ } else {
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Helper method to produce class output text file using the given handler
+ */
+ public static void processFile(ProcessingEnvironment processingEnv, String packageName, String fileName, Func1<PrintWriter, Void> handler) {
+ PrintWriter writer = null;
+ try {
+ Writer out;
+ Filer filer = processingEnv.getFiler();
+ FileObject resource;
+ try {
+ resource = filer.getResource(StandardLocation.CLASS_OUTPUT, packageName, fileName);
+ } catch (Throwable e) {
+ resource = filer.createResource(StandardLocation.CLASS_OUTPUT, packageName, fileName);
+ }
+ URI uri = resource.toUri();
+ File file = null;
+ if (uri != null) {
+ try {
+ file = new File(uri.getPath());
+ } catch (Exception e) {
+ warning(processingEnv, "Could not convert output directory resource URI to a file " + e);
+ }
+ }
+ if (file == null) {
+ warning(processingEnv, "No class output directory could be found!");
+ } else {
+ file.getParentFile().mkdirs();
+ out = new FileWriter(file);
+ writer = new PrintWriter(out);
+ handler.call(writer);
+ }
+ } catch (IOException e) {
+ log(processingEnv, e);
+ } finally {
+ if (writer != null) {
+ writer.close();
+ }
+ }
+ }
+
+ public static void log(ProcessingEnvironment processingEnv, String message) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message);
+ }
+
+ public static void warning(ProcessingEnvironment processingEnv, String message) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, message);
+ }
+
+ public static void error(ProcessingEnvironment processingEnv, String message) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message);
+ }
+
+ public static void log(ProcessingEnvironment processingEnv, Throwable e) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
+ StringWriter buffer = new StringWriter();
+ PrintWriter writer = new PrintWriter(buffer);
+ e.printStackTrace(writer);
+ writer.close();
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, buffer.toString());
+ }
+
+ public static String loadResource(ProcessingEnvironment processingEnv, String packageName, String fileName) {
+ Filer filer = processingEnv.getFiler();
+
+ FileObject resource;
+ try {
+ resource = filer.getResource(StandardLocation.CLASS_OUTPUT, "", packageName + "/" + fileName);
+ } catch (Throwable e) {
+ return "Crap" + e.getMessage();
+ }
+
+ if (resource == null) {
+ return null;
+ }
+
+ try {
+ InputStream is = resource.openInputStream();
+ return loadText(is, true);
+ } catch (Exception e) {
+ warning(processingEnv, "Cannot load file");
+ }
+
+ return null;
+ }
+
+ public static void dumpExceptionToErrorFile(String fileName, String message, Throwable e) {
+ File file = new File(fileName);
+ try {
+ FileOutputStream fos = new FileOutputStream(file);
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ fos.write(message.getBytes());
+ fos.write("\n\n".getBytes());
+ fos.write(sw.toString().getBytes());
+ pw.close();
+ sw.close();
+ fos.close();
+ } catch (Throwable t) {
+ // ignore
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/8a18e284/tooling/apt/src/main/java/org/apache/camel/tools/apt/CamelContextAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/CamelContextAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/CamelContextAnnotationProcessor.java
deleted file mode 100644
index f8e6b71..0000000
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/CamelContextAnnotationProcessor.java
+++ /dev/null
@@ -1,720 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.tools.apt;
-
-import java.io.PrintWriter;
-import java.util.Comparator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-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.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-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.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementRef;
-import javax.xml.bind.annotation.XmlElements;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-
-import org.apache.camel.spi.Metadata;
-import org.apache.camel.tools.apt.helper.JsonSchemaHelper;
-import org.apache.camel.tools.apt.helper.Strings;
-
-import static org.apache.camel.tools.apt.helper.JsonSchemaHelper.sanitizeDescription;
-import static org.apache.camel.tools.apt.helper.Strings.canonicalClassName;
-import static org.apache.camel.tools.apt.helper.Strings.isNullOrEmpty;
-import static org.apache.camel.tools.apt.helper.Strings.safeNull;
-
-/**
- * Process camel-spring's <camelContext> and generate json schema documentation
- */
-@SupportedAnnotationTypes({"javax.xml.bind.annotation.*", "org.apache.camel.spi.Label"})
-@SupportedSourceVersion(SourceVersion.RELEASE_8)
-public class CamelContextAnnotationProcessor extends AbstractAnnotationProcessor {
-
- private static final String ONE_OF_TYPE_NAME = "";
- private boolean skipUnwanted = true;
-
- @Override
- public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
- try {
- if (roundEnv.processingOver()) {
- return true;
- }
-
- Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(XmlRootElement.class);
- for (Element element : elements) {
- if (element instanceof TypeElement) {
- processModelClass(roundEnv, (TypeElement) element);
- }
- }
- } catch (Throwable e) {
- dumpExceptionToErrorFile("camel-apt-error.log", "Error processing CamelContext model", e);
- }
- return true;
- }
-
- protected void processModelClass(final RoundEnvironment roundEnv, final TypeElement classElement) {
- // must be from camel-spring or camel-core-xml
- final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
- String packageName = javaTypeName.substring(0, javaTypeName.lastIndexOf("."));
- boolean valid = javaTypeName.startsWith("org.apache.camel.spring") || javaTypeName.startsWith("org.apache.camel.core.xml");
- if (!valid) {
- return;
- }
-
- // skip abstract classes
- if (classElement.getModifiers().contains(Modifier.ABSTRACT)) {
- return;
- }
-
- // skip unwanted classes which are "abstract" holders
- if (skipUnwanted) {
- if (classElement.getQualifiedName().toString().equals(ONE_OF_TYPE_NAME)) {
- return;
- }
- }
-
- final XmlRootElement rootElement = classElement.getAnnotation(XmlRootElement.class);
- if (rootElement == null) {
- return;
- }
-
- String aName = rootElement.name();
- if (isNullOrEmpty(aName) || "##default".equals(aName)) {
- XmlType typeElement = classElement.getAnnotation(XmlType.class);
- aName = typeElement.name();
- }
- final String name = aName;
-
- // 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
- Func1<PrintWriter, Void> handler = new Func1<PrintWriter, Void>() {
- @Override
- public Void call(PrintWriter writer) {
- writeJSonSchemeDocumentation(writer, roundEnv, classElement, rootElement, javaTypeName, name);
- return null;
- }
- };
- processFile(packageName, fileName, handler);
- }
-
- protected void writeJSonSchemeDocumentation(PrintWriter writer, RoundEnvironment roundEnv, TypeElement classElement, XmlRootElement rootElement,
- String javaTypeName, String modelName) {
- // gather eip information
- EipModel eipModel = findEipModelProperties(roundEnv, classElement, javaTypeName, modelName);
-
- // collect eip information
- Set<EipOption> eipOptions = new TreeSet<EipOption>(new EipOptionComparator(eipModel));
- findClassProperties(writer, roundEnv, eipOptions, classElement, classElement, "", modelName);
-
- String json = createParameterJsonSchema(eipModel, eipOptions);
- writer.println(json);
- }
-
- public String createParameterJsonSchema(EipModel eipModel, Set<EipOption> options) {
- StringBuilder buffer = new StringBuilder("{");
- // eip model
- buffer.append("\n \"model\": {");
- buffer.append("\n \"kind\": \"").append("model").append("\",");
- buffer.append("\n \"name\": \"").append(eipModel.getName()).append("\",");
- if (eipModel.getTitle() != null) {
- buffer.append("\n \"title\": \"").append(eipModel.getTitle()).append("\",");
- } else {
- // fallback and use name as title
- buffer.append("\n \"title\": \"").append(asTitle(eipModel.getName())).append("\",");
- }
- buffer.append("\n \"description\": \"").append(safeNull(eipModel.getDescription())).append("\",");
- buffer.append("\n \"javaType\": \"").append(eipModel.getJavaType()).append("\",");
- buffer.append("\n \"label\": \"").append(safeNull(eipModel.getLabel())).append("\"");
- buffer.append("\n },");
-
- buffer.append("\n \"properties\": {");
- boolean first = true;
- for (EipOption entry : options) {
- if (first) {
- first = false;
- } else {
- buffer.append(",");
- }
- buffer.append("\n ");
- // as its json we need to sanitize the docs
- String doc = entry.getDocumentation();
- doc = sanitizeDescription(doc, false);
- buffer.append(JsonSchemaHelper.toJson(entry.getName(), entry.getKind(), entry.isRequired(), entry.getType(), entry.getDefaultValue(), doc,
- entry.isDeprecated(), false, null, null, entry.isEnumType(), entry.getEnums(), entry.isOneOf(), entry.getOneOfTypes(), null, null, false));
- }
- buffer.append("\n }");
-
- buffer.append("\n}\n");
- return buffer.toString();
- }
-
- protected EipModel findEipModelProperties(RoundEnvironment roundEnv, TypeElement classElement, String javaTypeName, String name) {
- EipModel model = new EipModel();
- model.setJavaType(javaTypeName);
- model.setName(name);
-
- Metadata metadata = classElement.getAnnotation(Metadata.class);
- if (metadata != null) {
- if (!Strings.isNullOrEmpty(metadata.label())) {
- model.setLabel(metadata.label());
- }
- if (!Strings.isNullOrEmpty(metadata.title())) {
- model.setTitle(metadata.title());
- }
- }
-
- // favor to use class javadoc of component as description
- if (model.getJavaType() != null) {
- Elements elementUtils = processingEnv.getElementUtils();
- TypeElement typeElement = findTypeElement(roundEnv, model.getJavaType());
- if (typeElement != null) {
- String doc = elementUtils.getDocComment(typeElement);
- if (doc != null) {
- // need to sanitize the description first (we only want a summary)
- doc = sanitizeDescription(doc, true);
- // the javadoc may actually be empty, so only change the doc if we got something
- if (!Strings.isNullOrEmpty(doc)) {
- model.setDescription(doc);
- }
- }
- }
- }
-
- return model;
- }
-
- protected void findClassProperties(PrintWriter writer, RoundEnvironment roundEnv, Set<EipOption> eipOptions,
- TypeElement originalClassType, TypeElement classElement, String prefix, String modelName) {
- while (true) {
- List<VariableElement> fieldElements = ElementFilter.fieldsIn(classElement.getEnclosedElements());
- for (VariableElement fieldElement : fieldElements) {
-
- String fieldName = fieldElement.getSimpleName().toString();
-
- XmlAttribute attribute = fieldElement.getAnnotation(XmlAttribute.class);
- if (attribute != null) {
- boolean skip = processAttribute(roundEnv, originalClassType, classElement, fieldElement, fieldName, attribute, eipOptions, prefix, modelName);
- if (skip) {
- continue;
- }
- }
-
- XmlElements elements = fieldElement.getAnnotation(XmlElements.class);
- if (elements != null) {
- processElements(roundEnv, classElement, elements, fieldElement, eipOptions, prefix);
- }
-
- XmlElementRef elementRef = fieldElement.getAnnotation(XmlElementRef.class);
- if (elementRef != null) {
- processElement(roundEnv, classElement, null, elementRef, fieldElement, eipOptions, prefix);
- }
-
- XmlElement element = fieldElement.getAnnotation(XmlElement.class);
- if (element != null) {
- if ("rests".equals(fieldName)) {
- processRests(roundEnv, classElement, element, fieldElement, fieldName, eipOptions, prefix);
- } else if ("routes".equals(fieldName)) {
- processRoutes(roundEnv, classElement, element, fieldElement, fieldName, eipOptions, prefix);
- } else {
- processElement(roundEnv, classElement, element, null, fieldElement, eipOptions, prefix);
- }
- }
- }
-
- // check super classes which may also have fields
- TypeElement baseTypeElement = null;
- TypeMirror superclass = classElement.getSuperclass();
- if (superclass != null) {
- String superClassName = canonicalClassName(superclass.toString());
- baseTypeElement = findTypeElement(roundEnv, superClassName);
- }
- if (baseTypeElement != null) {
- classElement = baseTypeElement;
- } else {
- break;
- }
- }
- }
-
- private boolean processAttribute(RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement, VariableElement fieldElement,
- String fieldName, XmlAttribute attribute, Set<EipOption> eipOptions, String prefix, String modelName) {
- Elements elementUtils = processingEnv.getElementUtils();
-
- String name = attribute.name();
- if (isNullOrEmpty(name) || "##default".equals(name)) {
- name = fieldName;
- }
-
- // lets skip some unwanted attributes
- if (skipUnwanted) {
- }
-
- name = prefix + name;
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
- TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
-
- String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
- if (isNullOrEmpty(docComment)) {
- Metadata metadata = fieldElement.getAnnotation(Metadata.class);
- docComment = metadata != null ? metadata.description() : null;
- }
- boolean required = attribute.required();
- // metadata may overrule element required
- required = findRequired(fieldElement, required);
-
- // gather enums
- Set<String> enums = new TreeSet<String>();
- boolean isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
- if (isEnum) {
- TypeElement enumClass = findTypeElement(roundEnv, fieldTypeElement.asType().toString());
- // find all the enum constants which has the possible enum value that can be used
- List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
- for (VariableElement var : fields) {
- if (var.getKind() == ElementKind.ENUM_CONSTANT) {
- String val = var.toString();
- enums.add(val);
- }
- }
- }
-
- boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
-
- // special for id as its inherited from camel-core
- if ("id".equals(name) && isNullOrEmpty(docComment)) {
- if ("CamelContextFactoryBean".equals(originalClassType.getSimpleName().toString())) {
- docComment = "Sets the id (name) of this CamelContext";
- } else {
- docComment = "Sets the id of this node";
- }
- }
-
- EipOption ep = new EipOption(name, "attribute", fieldTypeName, required, defaultValue, docComment, deprecated, isEnum, enums, false, null);
- eipOptions.add(ep);
-
- return false;
- }
-
- /**
- * Special for processing an @XmlElement routes field
- */
- private void processRoutes(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElement element,
- VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
-
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- Set<String> oneOfTypes = new TreeSet<String>();
- oneOfTypes.add("route");
-
- EipOption ep = new EipOption("route", "element", fieldTypeName, false, "", "Contains the Camel routes", false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
-
- /**
- * Special for processing an @XmlElement rests field
- */
- private void processRests(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElement element,
- VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
-
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- Set<String> oneOfTypes = new TreeSet<String>();
- oneOfTypes.add("rest");
-
- EipOption ep = new EipOption("rest", "element", fieldTypeName, false, "", "Contains the rest services defined using the rest-dsl", false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
-
- private void processElement(RoundEnvironment roundEnv, TypeElement classElement, XmlElement element, XmlElementRef elementRef, VariableElement fieldElement,
- Set<EipOption> eipOptions, String prefix) {
- Elements elementUtils = processingEnv.getElementUtils();
-
- String fieldName;
- fieldName = fieldElement.getSimpleName().toString();
- if (element != null || elementRef != null) {
-
- String kind = "element";
- String name = element != null ? element.name() : elementRef.name();
- if (isNullOrEmpty(name) || "##default".equals(name)) {
- name = fieldName;
- }
- name = prefix + name;
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
- TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
-
- String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
- if (isNullOrEmpty(docComment)) {
- Metadata metadata = fieldElement.getAnnotation(Metadata.class);
- docComment = metadata != null ? metadata.description() : null;
- }
- boolean required = element != null ? element.required() : elementRef.required();
- // metadata may overrule element required
- required = findRequired(fieldElement, required);
-
- // gather enums
- Set<String> enums = new LinkedHashSet<String>();
- boolean isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
- if (isEnum) {
- TypeElement enumClass = findTypeElement(roundEnv, fieldTypeElement.asType().toString());
- // find all the enum constants which has the possible enum value that can be used
- List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
- for (VariableElement var : fields) {
- if (var.getKind() == ElementKind.ENUM_CONSTANT) {
- String val = var.toString();
- enums.add(val);
- }
- }
- }
-
- // is it a definition/factory-bean type then its a oneOf
- TreeSet oneOfTypes = new TreeSet<String>();
- if (fieldTypeName.endsWith("Definition") || fieldTypeName.endsWith("FactoryBean")) {
- TypeElement definitionClass = findTypeElement(roundEnv, fieldTypeElement.asType().toString());
- if (definitionClass != null) {
- XmlRootElement rootElement = definitionClass.getAnnotation(XmlRootElement.class);
- if (rootElement != null) {
- String childName = rootElement.name();
- if (childName != null) {
- oneOfTypes.add(childName);
- }
- }
- }
- } else if (fieldTypeName.endsWith("Definition>") || fieldTypeName.endsWith("FactoryBean>")) {
- // its a list so we need to load the generic type
- String typeName = Strings.between(fieldTypeName, "<", ">");
- TypeElement definitionClass = findTypeElement(roundEnv, typeName);
- if (definitionClass != null) {
- XmlRootElement rootElement = definitionClass.getAnnotation(XmlRootElement.class);
- if (rootElement != null) {
- String childName = rootElement.name();
- if (childName != null) {
- oneOfTypes.add(childName);
- }
- }
- }
- }
- boolean oneOf = !oneOfTypes.isEmpty();
-
- boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
-
- EipOption ep = new EipOption(name, kind, fieldTypeName, required, defaultValue, docComment, deprecated, isEnum, enums, oneOf, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- private void processElements(RoundEnvironment roundEnv, TypeElement classElement, XmlElements elements, VariableElement fieldElement,
- Set<EipOption> eipOptions, String prefix) {
- Elements elementUtils = processingEnv.getElementUtils();
-
- String fieldName;
- fieldName = fieldElement.getSimpleName().toString();
- if (elements != null) {
- String kind = "element";
- String name = fieldName;
- name = prefix + name;
-
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
- if (isNullOrEmpty(docComment)) {
- Metadata metadata = fieldElement.getAnnotation(Metadata.class);
- docComment = metadata != null ? metadata.description() : null;
- }
- boolean required = false;
- required = findRequired(fieldElement, required);
-
- // gather oneOf of the elements
- Set<String> oneOfTypes = new TreeSet<String>();
- for (XmlElement element : elements.value()) {
- String child = element.name();
- oneOfTypes.add(child);
- }
-
- EipOption ep = new EipOption(name, kind, fieldTypeName, required, defaultValue, docComment, false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- private String findDefaultValue(VariableElement fieldElement, String fieldTypeName) {
- String defaultValue = null;
- Metadata metadata = fieldElement.getAnnotation(Metadata.class);
- if (metadata != null) {
- if (!Strings.isNullOrEmpty(metadata.defaultValue())) {
- defaultValue = metadata.defaultValue();
- }
- }
- if (defaultValue == null) {
- // if its a boolean type, then we use false as the default
- if ("boolean".equals(fieldTypeName) || "java.lang.Boolean".equals(fieldTypeName)) {
- defaultValue = "false";
- }
- }
-
- return defaultValue;
- }
-
- private boolean findRequired(VariableElement fieldElement, boolean defaultValue) {
- Metadata metadata = fieldElement.getAnnotation(Metadata.class);
- if (metadata != null) {
- if (!Strings.isNullOrEmpty(metadata.required())) {
- defaultValue = "true".equals(metadata.required());
- }
- }
- return defaultValue;
- }
-
- /**
- * Capitializes the name as a title
- *
- * @param name the name
- * @return as a title
- */
- private static String asTitle(String name) {
- StringBuilder sb = new StringBuilder();
- for (char c : name.toCharArray()) {
- boolean upper = Character.isUpperCase(c);
- boolean first = sb.length() == 0;
- if (first) {
- sb.append(Character.toUpperCase(c));
- } else if (upper) {
- sb.append(' ');
- sb.append(c);
- } else {
- sb.append(Character.toLowerCase(c));
- }
- }
- return sb.toString().trim();
- }
-
- private static final class EipModel {
-
- private String name;
- private String title;
- private String javaType;
- private String label;
- private String description;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getJavaType() {
- return javaType;
- }
-
- public void setJavaType(String javaType) {
- this.javaType = javaType;
- }
-
- public String getLabel() {
- return label;
- }
-
- public void setLabel(String label) {
- this.label = label;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- }
-
- private static final class EipOption {
-
- private String name;
- private String kind;
- private String type;
- private boolean required;
- private String defaultValue;
- private String documentation;
- private boolean deprecated;
- 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 documentation, boolean deprecated,
- boolean enumType, Set<String> enums, boolean oneOf, Set<String> oneOfTypes) {
- this.name = name;
- this.kind = kind;
- this.type = type;
- this.required = required;
- this.defaultValue = defaultValue;
- this.documentation = documentation;
- this.deprecated = deprecated;
- this.enumType = enumType;
- this.enums = enums;
- this.oneOf = oneOf;
- this.oneOfTypes = oneOfTypes;
- }
-
- public String getName() {
- return name;
- }
-
- public String getKind() {
- return kind;
- }
-
- public String getType() {
- return type;
- }
-
- public boolean isRequired() {
- return required;
- }
-
- public String getDefaultValue() {
- return defaultValue;
- }
-
- public String getDocumentation() {
- return documentation;
- }
-
- public boolean isDeprecated() {
- return deprecated;
- }
-
- public boolean isEnumType() {
- return enumType;
- }
-
- public Set<String> getEnums() {
- return enums;
- }
-
- public boolean isOneOf() {
- return oneOf;
- }
-
- public Set<String> getOneOfTypes() {
- return oneOfTypes;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- EipOption that = (EipOption) o;
-
- if (!name.equals(that.name)) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return name.hashCode();
- }
- }
-
- private static final class EipOptionComparator implements Comparator<EipOption> {
-
- private final EipModel model;
-
- private EipOptionComparator(EipModel model) {
- this.model = model;
- }
-
- @Override
- public int compare(EipOption o1, EipOption o2) {
- int weigth = weigth(o1);
- int weigth2 = weigth(o2);
-
- if (weigth == weigth2) {
- // keep the current order
- return 1;
- } else {
- // sort according to weight
- return weigth2 - weigth;
- }
- }
-
- private int weigth(EipOption o) {
- String name = o.getName();
-
- // these should be first
- if ("expression".equals(name)) {
- return 10;
- }
-
- // these should be last
- if ("description".equals(name)) {
- return -10;
- } else if ("id".equals(name)) {
- return -9;
- } else if ("pattern".equals(name) && "to".equals(model.getName())) {
- // and pattern only for the to model
- return -8;
- }
- return 0;
- }
- }
-
-}
[2/4] camel git commit: CAMEL-9482: Adjust the apt to make camel-core
compile again,
seems like we need to merge the core/spring into a single apt as the compiler
cannot do both on camel-core for some odd reason.
Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/8a18e284/tooling/apt/src/main/java/org/apache/camel/tools/apt/EipAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EipAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EipAnnotationProcessor.java
deleted file mode 100644
index 253e37f..0000000
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EipAnnotationProcessor.java
+++ /dev/null
@@ -1,1148 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.tools.apt;
-
-import java.io.PrintWriter;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-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.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-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.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementRef;
-import javax.xml.bind.annotation.XmlElements;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-import org.apache.camel.spi.Metadata;
-import org.apache.camel.tools.apt.helper.JsonSchemaHelper;
-import org.apache.camel.tools.apt.helper.Strings;
-
-import static org.apache.camel.tools.apt.helper.JsonSchemaHelper.sanitizeDescription;
-import static org.apache.camel.tools.apt.helper.Strings.canonicalClassName;
-import static org.apache.camel.tools.apt.helper.Strings.isNullOrEmpty;
-import static org.apache.camel.tools.apt.helper.Strings.safeNull;
-
-/**
- * Process all camel-core's model classes (EIPs and DSL) and generate json schema documentation
- */
-@SupportedAnnotationTypes({"javax.xml.bind.annotation.*", "org.apache.camel.spi.Label"})
-@SupportedSourceVersion(SourceVersion.RELEASE_8)
-public class EipAnnotationProcessor extends AbstractAnnotationProcessor {
-
- // special when using expression/predicates in the model
- private static final String ONE_OF_TYPE_NAME = "org.apache.camel.model.ExpressionSubElementDefinition";
- private static final String[] ONE_OF_LANGUAGES = new String[]{
- "org.apache.camel.model.language.ExpressionDefinition",
- "org.apache.camel.model.language.NamespaceAwareExpression"
- };
- // special for inputs (these classes have sub classes, so we use this to find all classes)
- private static final String[] ONE_OF_INPUTS = new String[]{
- "org.apache.camel.model.ProcessorDefinition",
- "org.apache.camel.model.VerbDefinition"
- };
- // special for outputs (these classes have sub classes, so we use this to find all classes)
- private static final String[] ONE_OF_OUTPUTS = new String[]{
- "org.apache.camel.model.ProcessorDefinition",
- "org.apache.camel.model.NoOutputDefinition",
- "org.apache.camel.model.OutputDefinition",
- "org.apache.camel.model.ExpressionNode",
- "org.apache.camel.model.NoOutputExpressionNode",
- "org.apache.camel.model.SendDefinition",
- "org.apache.camel.model.InterceptDefinition",
- "org.apache.camel.model.WhenDefinition",
- "org.apache.camel.model.ToDynamicDefinition"
- };
- // special for verbs (these classes have sub classes, so we use this to find all classes)
- private static final String[] ONE_OF_VERBS = new String[]{
- "org.apache.camel.model.rest.VerbDefinition"
- };
-
- private boolean skipUnwanted = true;
-
- @Override
- public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
- try {
- if (roundEnv.processingOver()) {
- return true;
- }
-
- Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(XmlRootElement.class);
- for (Element element : elements) {
- if (element instanceof TypeElement) {
- processModelClass(roundEnv, (TypeElement) element);
- }
- }
- } catch (Throwable e) {
- dumpExceptionToErrorFile("camel-apt-error.log", "Error processing EIP model", e);
- }
- return true;
- }
-
- protected void processModelClass(final RoundEnvironment roundEnv, final TypeElement classElement) {
- // must be from org.apache.camel.model
- final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
- String packageName = javaTypeName.substring(0, javaTypeName.lastIndexOf("."));
- if (!javaTypeName.startsWith("org.apache.camel.model")) {
- return;
- }
-
- // skip abstract classes
- if (classElement.getModifiers().contains(Modifier.ABSTRACT)) {
- return;
- }
-
- // skip unwanted classes which are "abstract" holders
- if (skipUnwanted) {
- if (classElement.getQualifiedName().toString().equals(ONE_OF_TYPE_NAME)) {
- return;
- }
- }
-
- final XmlRootElement rootElement = classElement.getAnnotation(XmlRootElement.class);
- if (rootElement == null) {
- return;
- }
-
- String aName = rootElement.name();
- if (isNullOrEmpty(aName) || "##default".equals(aName)) {
- XmlType typeElement = classElement.getAnnotation(XmlType.class);
- aName = typeElement.name();
- }
- final String name = aName;
-
- // 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
- Func1<PrintWriter, Void> handler = new Func1<PrintWriter, Void>() {
- @Override
- public Void call(PrintWriter writer) {
- writeJSonSchemeDocumentation(writer, roundEnv, classElement, rootElement, javaTypeName, name);
- return null;
- }
- };
- processFile(packageName, fileName, handler);
- }
-
- protected void writeJSonSchemeDocumentation(PrintWriter writer, RoundEnvironment roundEnv, TypeElement classElement, XmlRootElement rootElement,
- String javaTypeName, String modelName) {
- // gather eip information
- EipModel eipModel = findEipModelProperties(roundEnv, classElement, javaTypeName, modelName);
-
- // get endpoint information which is divided into paths and options (though there should really only be one path)
- Set<EipOption> eipOptions = new TreeSet<EipOption>(new EipOptionComparator(eipModel));
- findClassProperties(writer, roundEnv, eipOptions, classElement, classElement, "", modelName);
-
- // after we have found all the options then figure out if the model accepts input/output
- eipModel.setInput(hasInput(roundEnv, classElement));
- eipModel.setOutput(hasOutput(eipModel, eipOptions));
-
- String json = createParameterJsonSchema(eipModel, eipOptions);
- writer.println(json);
- }
-
- public String createParameterJsonSchema(EipModel eipModel, Set<EipOption> options) {
- StringBuilder buffer = new StringBuilder("{");
- // eip model
- buffer.append("\n \"model\": {");
- buffer.append("\n \"kind\": \"").append("model").append("\",");
- buffer.append("\n \"name\": \"").append(eipModel.getName()).append("\",");
- if (eipModel.getTitle() != null) {
- buffer.append("\n \"title\": \"").append(eipModel.getTitle()).append("\",");
- } else {
- // fallback and use name as title
- buffer.append("\n \"title\": \"").append(asTitle(eipModel.getName())).append("\",");
- }
- buffer.append("\n \"description\": \"").append(safeNull(eipModel.getDescription())).append("\",");
- buffer.append("\n \"javaType\": \"").append(eipModel.getJavaType()).append("\",");
- buffer.append("\n \"label\": \"").append(safeNull(eipModel.getLabel())).append("\",");
- buffer.append("\n \"input\": \"").append(eipModel.getInput()).append("\",");
- buffer.append("\n \"output\": \"").append(eipModel.getOutput()).append("\"");
- buffer.append("\n },");
-
- buffer.append("\n \"properties\": {");
- boolean first = true;
- for (EipOption entry : options) {
- if (first) {
- first = false;
- } else {
- buffer.append(",");
- }
- buffer.append("\n ");
- // as its json we need to sanitize the docs
- String doc = entry.getDocumentation();
- doc = sanitizeDescription(doc, false);
- buffer.append(JsonSchemaHelper.toJson(entry.getName(), entry.getKind(), entry.isRequired(), entry.getType(), entry.getDefaultValue(), doc,
- entry.isDeprecated(), false, null, null, entry.isEnumType(), entry.getEnums(), entry.isOneOf(), entry.getOneOfTypes(), null, null, false));
- }
- buffer.append("\n }");
-
- buffer.append("\n}\n");
- return buffer.toString();
- }
-
- protected EipModel findEipModelProperties(RoundEnvironment roundEnv, TypeElement classElement, String javaTypeName, String name) {
- EipModel model = new EipModel();
- model.setJavaType(javaTypeName);
- model.setName(name);
-
- Metadata metadata = classElement.getAnnotation(Metadata.class);
- if (metadata != null) {
- if (!Strings.isNullOrEmpty(metadata.label())) {
- model.setLabel(metadata.label());
- }
- if (!Strings.isNullOrEmpty(metadata.title())) {
- model.setTitle(metadata.title());
- }
- }
-
- // favor to use class javadoc of component as description
- if (model.getJavaType() != null) {
- Elements elementUtils = processingEnv.getElementUtils();
- TypeElement typeElement = findTypeElement(roundEnv, model.getJavaType());
- if (typeElement != null) {
- String doc = elementUtils.getDocComment(typeElement);
- if (doc != null) {
- // need to sanitize the description first (we only want a summary)
- doc = sanitizeDescription(doc, true);
- // the javadoc may actually be empty, so only change the doc if we got something
- if (!Strings.isNullOrEmpty(doc)) {
- model.setDescription(doc);
- }
- }
- }
- }
-
- return model;
- }
-
- protected void findClassProperties(PrintWriter writer, RoundEnvironment roundEnv, Set<EipOption> eipOptions,
- TypeElement originalClassType, TypeElement classElement, String prefix, String modelName) {
- while (true) {
- List<VariableElement> fieldElements = ElementFilter.fieldsIn(classElement.getEnclosedElements());
- for (VariableElement fieldElement : fieldElements) {
-
- String fieldName = fieldElement.getSimpleName().toString();
-
- XmlAttribute attribute = fieldElement.getAnnotation(XmlAttribute.class);
- if (attribute != null) {
- boolean skip = processAttribute(roundEnv, originalClassType, classElement, fieldElement, fieldName, attribute, eipOptions, prefix, modelName);
- if (skip) {
- continue;
- }
- }
-
- XmlValue value = fieldElement.getAnnotation(XmlValue.class);
- if (value != null) {
- processValue(roundEnv, originalClassType, classElement, fieldElement, fieldName, value, eipOptions, prefix, modelName);
- }
-
- XmlElements elements = fieldElement.getAnnotation(XmlElements.class);
- if (elements != null) {
- processElements(roundEnv, classElement, elements, fieldElement, eipOptions, prefix);
- }
-
- XmlElement element = fieldElement.getAnnotation(XmlElement.class);
- if (element != null) {
- processElement(roundEnv, classElement, element, fieldElement, eipOptions, prefix);
- }
-
- // special for eips which has outputs or requires an expressions
- XmlElementRef elementRef = fieldElement.getAnnotation(XmlElementRef.class);
- if (elementRef != null) {
-
- // special for routes
- processRoutes(roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
-
- // special for outputs
- processOutputs(roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
-
- // special for when clauses (choice eip)
- processRefWhenClauses(roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
-
- // special for rests (rest-dsl)
- processRests(roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
-
- // special for verbs (rest-dsl)
- processVerbs(roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix);
-
- // special for expression
- processRefExpression(roundEnv, originalClassType, classElement, elementRef, fieldElement, fieldName, eipOptions, prefix);
-
- }
- }
-
- // special when we process these nodes as they do not use JAXB annotations on fields, but on methods
- if ("OptionalIdentifiedDefinition".equals(classElement.getSimpleName().toString())) {
- processIdentified(roundEnv, originalClassType, classElement, eipOptions, prefix);
- } else if ("RouteDefinition".equals(classElement.getSimpleName().toString())) {
- processRoute(roundEnv, originalClassType, classElement, eipOptions, prefix);
- }
-
- // check super classes which may also have fields
- TypeElement baseTypeElement = null;
- TypeMirror superclass = classElement.getSuperclass();
- if (superclass != null) {
- String superClassName = canonicalClassName(superclass.toString());
- baseTypeElement = findTypeElement(roundEnv, superClassName);
- }
- if (baseTypeElement != null) {
- classElement = baseTypeElement;
- } else {
- break;
- }
- }
- }
-
- private boolean processAttribute(RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement, VariableElement fieldElement,
- String fieldName, XmlAttribute attribute, Set<EipOption> eipOptions, String prefix, String modelName) {
- Elements elementUtils = processingEnv.getElementUtils();
-
- String name = attribute.name();
- if (isNullOrEmpty(name) || "##default".equals(name)) {
- name = fieldName;
- }
-
- // lets skip some unwanted attributes
- if (skipUnwanted) {
- // we want to skip inheritErrorHandler which is only applicable for the load-balancer
- boolean loadBalancer = "LoadBalanceDefinition".equals(originalClassType.getSimpleName().toString());
- if (!loadBalancer && "inheritErrorHandler".equals(name)) {
- return true;
- }
- }
-
- name = prefix + name;
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
- TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
-
- String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
- boolean required = attribute.required();
- // metadata may overrule element required
- required = findRequired(fieldElement, required);
-
- // gather enums
- Set<String> enums = new TreeSet<String>();
- boolean isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
- if (isEnum) {
- TypeElement enumClass = findTypeElement(roundEnv, fieldTypeElement.asType().toString());
- // find all the enum constants which has the possible enum value that can be used
- List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
- for (VariableElement var : fields) {
- if (var.getKind() == ElementKind.ENUM_CONSTANT) {
- String val = var.toString();
- enums.add(val);
- }
- }
- }
-
- boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
-
- EipOption ep = new EipOption(name, "attribute", fieldTypeName, required, defaultValue, docComment, deprecated, isEnum, enums, false, null);
- eipOptions.add(ep);
-
- return false;
- }
-
- private void processValue(RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement, VariableElement fieldElement, String fieldName, XmlValue value,
- Set<EipOption> eipOptions, String prefix, String modelName) {
- Elements elementUtils = processingEnv.getElementUtils();
-
- // XmlValue has no name attribute
- String name = fieldName;
-
- if ("method".equals(modelName) || "tokenize".equals(modelName) || "xtokenize".equals(modelName)) {
- // skip expression attribute on these three languages as they are solely configured using attributes
- if ("expression".equals(name)) {
- return;
- }
- }
-
- name = prefix + name;
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
- boolean required = true;
- // metadata may overrule element required
- required = findRequired(fieldElement, required);
-
- boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
-
- EipOption ep = new EipOption(name, "value", fieldTypeName, required, defaultValue, docComment, deprecated, false, null, false, null);
- eipOptions.add(ep);
- }
-
- private void processElement(RoundEnvironment roundEnv, TypeElement classElement, XmlElement element, VariableElement fieldElement,
- Set<EipOption> eipOptions, String prefix) {
- Elements elementUtils = processingEnv.getElementUtils();
-
- String fieldName;
- fieldName = fieldElement.getSimpleName().toString();
- if (element != null) {
-
- String kind = "element";
- String name = element.name();
- if (isNullOrEmpty(name) || "##default".equals(name)) {
- name = fieldName;
- }
- name = prefix + name;
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
- TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
-
- String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
- boolean required = element.required();
- // metadata may overrule element required
- required = findRequired(fieldElement, required);
-
- // gather enums
- Set<String> enums = new LinkedHashSet<String>();
- boolean isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
- if (isEnum) {
- TypeElement enumClass = findTypeElement(roundEnv, fieldTypeElement.asType().toString());
- // find all the enum constants which has the possible enum value that can be used
- List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
- for (VariableElement var : fields) {
- if (var.getKind() == ElementKind.ENUM_CONSTANT) {
- String val = var.toString();
- enums.add(val);
- }
- }
- }
-
- // gather oneOf expression/predicates which uses language
- Set<String> oneOfTypes = new TreeSet<String>();
- boolean isOneOf = ONE_OF_TYPE_NAME.equals(fieldTypeName);
- if (isOneOf) {
- // okay its actually an language expression, so favor using that in the eip option
- kind = "expression";
- for (String language : ONE_OF_LANGUAGES) {
- fieldTypeName = language;
- TypeElement languages = findTypeElement(roundEnv, language);
- 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);
- }
- }
- }
- }
- }
- // special for otherwise as we want to indicate that the element is
- if ("otherwise".equals(name)) {
- isOneOf = true;
- oneOfTypes.add("otherwise");
- }
-
- boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
-
- EipOption ep = new EipOption(name, kind, fieldTypeName, required, defaultValue, docComment, deprecated, isEnum, enums, isOneOf, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- private void processElements(RoundEnvironment roundEnv, TypeElement classElement, XmlElements elements, VariableElement fieldElement,
- Set<EipOption> eipOptions, String prefix) {
- Elements elementUtils = processingEnv.getElementUtils();
-
- String fieldName;
- fieldName = fieldElement.getSimpleName().toString();
- if (elements != null) {
- String kind = "element";
- String name = fieldName;
- name = prefix + name;
-
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- String defaultValue = findDefaultValue(fieldElement, fieldTypeName);
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, true);
-
- boolean required = true;
- required = findRequired(fieldElement, required);
-
- // gather oneOf of the elements
- Set<String> oneOfTypes = new TreeSet<String>();
- for (XmlElement element : elements.value()) {
- String child = element.name();
- oneOfTypes.add(child);
- }
-
- EipOption ep = new EipOption(name, kind, fieldTypeName, required, defaultValue, docComment, false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- private void processRoute(RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement,
- Set<EipOption> eipOptions, String prefix) {
-
- Elements elementUtils = processingEnv.getElementUtils();
-
- // group
- String docComment = findJavaDoc(elementUtils, null, "group", null, classElement, true);
- EipOption ep = new EipOption("group", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // group
- docComment = findJavaDoc(elementUtils, null, "streamCache", null, classElement, true);
- ep = new EipOption("streamCache", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // trace
- docComment = findJavaDoc(elementUtils, null, "trace", null, classElement, true);
- ep = new EipOption("trace", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // trace
- docComment = findJavaDoc(elementUtils, null, "messageHistory", null, classElement, true);
- ep = new EipOption("messageHistory", "attribute", "java.lang.String", false, "true", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // trace
- docComment = findJavaDoc(elementUtils, null, "handleFault", null, classElement, true);
- ep = new EipOption("handleFault", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // delayer
- docComment = findJavaDoc(elementUtils, null, "delayer", null, classElement, true);
- ep = new EipOption("delayer", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // autoStartup
- docComment = findJavaDoc(elementUtils, null, "autoStartup", null, classElement, true);
- ep = new EipOption("autoStartup", "attribute", "java.lang.String", false, "true", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // startupOrder
- docComment = findJavaDoc(elementUtils, null, "startupOrder", null, classElement, true);
- ep = new EipOption("startupOrder", "attribute", "java.lang.Integer", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // errorHandlerRef
- docComment = findJavaDoc(elementUtils, null, "errorHandlerRef", null, classElement, true);
- ep = new EipOption("errorHandlerRef", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // routePolicyRef
- docComment = findJavaDoc(elementUtils, null, "routePolicyRef", null, classElement, true);
- ep = new EipOption("routePolicyRef", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // shutdownRoute
- Set<String> enums = new LinkedHashSet<String>();
- enums.add("Default");
- enums.add("Defer");
- docComment = findJavaDoc(elementUtils, null, "shutdownRoute", "Default", classElement, true);
- ep = new EipOption("shutdownRoute", "attribute", "org.apache.camel.ShutdownRoute", false, "", docComment, false, true, enums, false, null);
- eipOptions.add(ep);
-
- // shutdownRunningTask
- enums = new LinkedHashSet<String>();
- enums.add("CompleteCurrentTaskOnly");
- enums.add("CompleteAllTasks");
- docComment = findJavaDoc(elementUtils, null, "shutdownRunningTask", "CompleteCurrentTaskOnly", classElement, true);
- ep = new EipOption("shutdownRunningTask", "attribute", "org.apache.camel.ShutdownRunningTask", false, "", docComment, false, true, enums, false, null);
- eipOptions.add(ep);
-
- // inputs
- Set<String> oneOfTypes = new TreeSet<String>();
- oneOfTypes.add("from");
- docComment = findJavaDoc(elementUtils, null, "inputs", null, classElement, true);
- ep = new EipOption("inputs", "element", "java.util.List<org.apache.camel.model.FromDefinition>", true, "", docComment, false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
-
- // outputs
- // gather oneOf which extends any of the output base classes
- oneOfTypes = new TreeSet<String>();
- // find all classes that has that superClassName
- Set<TypeElement> children = new LinkedHashSet<TypeElement>();
- for (String superclass : ONE_OF_OUTPUTS) {
- findTypeElementChildren(roundEnv, children, superclass);
- }
- for (TypeElement child : children) {
- XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class);
- if (rootElement != null) {
- String childName = rootElement.name();
- if (childName != null) {
- oneOfTypes.add(childName);
- }
- }
- }
-
- // remove some types which are not intended as an output in eips
- oneOfTypes.remove("route");
-
- docComment = findJavaDoc(elementUtils, null, "outputs", null, classElement, true);
- ep = new EipOption("outputs", "element", "java.util.List<org.apache.camel.model.ProcessorDefinition<?>>", true, "", docComment, false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
-
- /**
- * Special for process the OptionalIdentifiedDefinition
- */
- private void processIdentified(RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement,
- Set<EipOption> eipOptions, String prefix) {
-
- Elements elementUtils = processingEnv.getElementUtils();
-
- // id
- String docComment = findJavaDoc(elementUtils, null, "id", null, classElement, true);
- EipOption ep = new EipOption("id", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // description
- docComment = findJavaDoc(elementUtils, null, "description", null, classElement, true);
- ep = new EipOption("description", "element", "org.apache.camel.model.DescriptionDefinition", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
-
- // lets skip custom id as it has no value for end users to configure
- if (!skipUnwanted) {
- // custom id
- docComment = findJavaDoc(elementUtils, null, "customId", null, classElement, true);
- ep = new EipOption("customId", "attribute", "java.lang.String", false, "", docComment, false, false, null, false, null);
- eipOptions.add(ep);
- }
- }
-
- /**
- * Special for processing an @XmlElementRef routes field
- */
- private void processRoutes(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
- VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
- if ("routes".equals(fieldName)) {
-
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- Set<String> oneOfTypes = new TreeSet<String>();
- oneOfTypes.add("route");
-
- EipOption ep = new EipOption("routes", "element", fieldTypeName, false, "", "Contains the Camel routes", false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- /**
- * Special for processing an @XmlElementRef rests field
- */
- private void processRests(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
- VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
- if ("rests".equals(fieldName)) {
-
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- Set<String> oneOfTypes = new TreeSet<String>();
- oneOfTypes.add("rest");
-
- EipOption ep = new EipOption("rests", "element", fieldTypeName, false, "", "Contains the rest services defined using the rest-dsl", false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- /**
- * Special for processing an @XmlElementRef outputs field
- */
- private void processOutputs(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
- VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
- if ("outputs".equals(fieldName) && supportOutputs(originalClassType)) {
- String kind = "element";
- String name = elementRef.name();
- if (isNullOrEmpty(name) || "##default".equals(name)) {
- name = fieldName;
- }
- name = prefix + name;
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- // gather oneOf which extends any of the output base classes
- Set<String> oneOfTypes = new TreeSet<String>();
- // find all classes that has that superClassName
- Set<TypeElement> children = new LinkedHashSet<TypeElement>();
- for (String superclass : ONE_OF_OUTPUTS) {
- findTypeElementChildren(roundEnv, children, superclass);
- }
- for (TypeElement child : children) {
- XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class);
- if (rootElement != null) {
- String childName = rootElement.name();
- if (childName != null) {
- oneOfTypes.add(childName);
- }
- }
- }
-
- // remove some types which are not intended as an output in eips
- oneOfTypes.remove("route");
-
- EipOption ep = new EipOption(name, kind, fieldTypeName, true, "", "", false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- /**
- * Special for processing an @XmlElementRef verbs field (rest-dsl)
- */
- private void processVerbs(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
- VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
-
- Elements elementUtils = processingEnv.getElementUtils();
-
- if ("verbs".equals(fieldName) && supportOutputs(originalClassType)) {
- String kind = "element";
- String name = elementRef.name();
- if (isNullOrEmpty(name) || "##default".equals(name)) {
- name = fieldName;
- }
- name = prefix + name;
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, originalClassType, true);
-
- // gather oneOf which extends any of the output base classes
- Set<String> oneOfTypes = new TreeSet<String>();
- // find all classes that has that superClassName
- Set<TypeElement> children = new LinkedHashSet<TypeElement>();
- for (String superclass : ONE_OF_VERBS) {
- findTypeElementChildren(roundEnv, children, superclass);
- }
- 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, true, "", docComment, false, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- /**
- * Special for processing an @XmlElementRef expression field
- */
- private void processRefExpression(RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement,
- XmlElementRef elementRef, VariableElement fieldElement,
- String fieldName, Set<EipOption> eipOptions, String prefix) {
- Elements elementUtils = processingEnv.getElementUtils();
-
- if ("expression".equals(fieldName)) {
- String kind = "expression";
- String name = elementRef.name();
- if (isNullOrEmpty(name) || "##default".equals(name)) {
- name = fieldName;
- }
- name = prefix + name;
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- // find javadoc from original class as it will override the setExpression method where we can provide the javadoc for the given EIP
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, originalClassType, true);
-
- // gather oneOf expression/predicates which uses language
- Set<String> oneOfTypes = new TreeSet<String>();
- for (String language : ONE_OF_LANGUAGES) {
- TypeElement languages = findTypeElement(roundEnv, language);
- 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);
- }
- }
- }
- }
-
- boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
-
- EipOption ep = new EipOption(name, kind, fieldTypeName, true, "", docComment, deprecated, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- /**
- * Special for processing an @XmlElementRef when field
- */
- private void processRefWhenClauses(RoundEnvironment roundEnv, TypeElement originalClassType, XmlElementRef elementRef,
- VariableElement fieldElement, String fieldName, Set<EipOption> eipOptions, String prefix) {
- Elements elementUtils = processingEnv.getElementUtils();
-
- if ("whenClauses".equals(fieldName)) {
- String kind = "element";
- String name = elementRef.name();
- if (isNullOrEmpty(name) || "##default".equals(name)) {
- name = fieldName;
- }
- name = prefix + name;
- TypeMirror fieldType = fieldElement.asType();
- String fieldTypeName = fieldType.toString();
-
- // find javadoc from original class as it will override the setExpression method where we can provide the javadoc for the given EIP
- String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, originalClassType, true);
- boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null;
-
- // indicate that this element is one of when
- Set<String> oneOfTypes = new HashSet<String>();
- oneOfTypes.add("when");
-
- EipOption ep = new EipOption(name, kind, fieldTypeName, false, "", docComment, deprecated, false, null, true, oneOfTypes);
- eipOptions.add(ep);
- }
- }
-
- /**
- * Whether the class supports outputs.
- * <p/>
- * There are some classes which does not support outputs, even though they have a outputs element.
- */
- private boolean supportOutputs(TypeElement classElement) {
- String superclass = canonicalClassName(classElement.getSuperclass().toString());
- return !"org.apache.camel.model.NoOutputExpressionNode".equals(superclass);
- }
-
- private String findDefaultValue(VariableElement fieldElement, String fieldTypeName) {
- String defaultValue = null;
- Metadata metadata = fieldElement.getAnnotation(Metadata.class);
- if (metadata != null) {
- if (!Strings.isNullOrEmpty(metadata.defaultValue())) {
- defaultValue = metadata.defaultValue();
- }
- }
- if (defaultValue == null) {
- // if its a boolean type, then we use false as the default
- if ("boolean".equals(fieldTypeName) || "java.lang.Boolean".equals(fieldTypeName)) {
- defaultValue = "false";
- }
- }
-
- return defaultValue;
- }
-
- private boolean findRequired(VariableElement fieldElement, boolean defaultValue) {
- Metadata metadata = fieldElement.getAnnotation(Metadata.class);
- if (metadata != null) {
- if (!Strings.isNullOrEmpty(metadata.required())) {
- defaultValue = "true".equals(metadata.required());
- }
- }
- return defaultValue;
- }
-
- /**
- * Capitializes the name as a title
- *
- * @param name the name
- * @return as a title
- */
- private static String asTitle(String name) {
- StringBuilder sb = new StringBuilder();
- for (char c : name.toCharArray()) {
- boolean upper = Character.isUpperCase(c);
- boolean first = sb.length() == 0;
- if (first) {
- sb.append(Character.toUpperCase(c));
- } else if (upper) {
- sb.append(' ');
- sb.append(c);
- } else {
- sb.append(Character.toLowerCase(c));
- }
- }
- return sb.toString().trim();
- }
-
- private boolean hasInput(RoundEnvironment roundEnv, TypeElement classElement) {
- for (String name : ONE_OF_INPUTS) {
- if (hasSuperClass(roundEnv, classElement, name)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean hasOutput(EipModel model, Set<EipOption> options) {
- // if we are route/rest then we accept output
- if ("route".equals(model.getName()) || "rest".equals(model.getName())) {
- return true;
- }
-
- for (EipOption option : options) {
- if ("outputs".equals(option.getName())) {
- return true;
- }
- }
- return false;
- }
-
- private static final class EipModel {
-
- private String name;
- private String title;
- private String javaType;
- private String label;
- private String description;
- private boolean input;
- private boolean output;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getJavaType() {
- return javaType;
- }
-
- public void setJavaType(String javaType) {
- this.javaType = javaType;
- }
-
- public String getLabel() {
- return label;
- }
-
- public void setLabel(String label) {
- this.label = label;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public boolean isInput() {
- return input;
- }
-
- public void setInput(boolean input) {
- this.input = input;
- }
-
- public String getInput() {
- return input ? "true" : "false";
- }
-
- public boolean isOutput() {
- return output;
- }
-
- public void setOutput(boolean output) {
- this.output = output;
- }
-
- public String getOutput() {
- return output ? "true" : "false";
- }
-
- }
-
- private static final class EipOption {
-
- private String name;
- private String kind;
- private String type;
- private boolean required;
- private String defaultValue;
- private String documentation;
- private boolean deprecated;
- 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 documentation, boolean deprecated,
- boolean enumType, Set<String> enums, boolean oneOf, Set<String> oneOfTypes) {
- this.name = name;
- this.kind = kind;
- this.type = type;
- this.required = required;
- this.defaultValue = defaultValue;
- this.documentation = documentation;
- this.deprecated = deprecated;
- this.enumType = enumType;
- this.enums = enums;
- this.oneOf = oneOf;
- this.oneOfTypes = oneOfTypes;
- }
-
- public String getName() {
- return name;
- }
-
- public String getKind() {
- return kind;
- }
-
- public String getType() {
- return type;
- }
-
- public boolean isRequired() {
- return required;
- }
-
- public String getDefaultValue() {
- return defaultValue;
- }
-
- public String getDocumentation() {
- return documentation;
- }
-
- public boolean isDeprecated() {
- return deprecated;
- }
-
- public boolean isEnumType() {
- return enumType;
- }
-
- public Set<String> getEnums() {
- return enums;
- }
-
- public boolean isOneOf() {
- return oneOf;
- }
-
- public Set<String> getOneOfTypes() {
- return oneOfTypes;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- EipOption that = (EipOption) o;
-
- if (!name.equals(that.name)) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return name.hashCode();
- }
- }
-
- private static final class EipOptionComparator implements Comparator<EipOption> {
-
- private final EipModel model;
-
- private EipOptionComparator(EipModel model) {
- this.model = model;
- }
-
- @Override
- public int compare(EipOption o1, EipOption o2) {
- int weigth = weigth(o1);
- int weigth2 = weigth(o2);
-
- if (weigth == weigth2) {
- // keep the current order
- return 1;
- } else {
- // sort according to weight
- return weigth2 - weigth;
- }
- }
-
- private int weigth(EipOption o) {
- String name = o.getName();
-
- // these should be first
- if ("expression".equals(name)) {
- return 10;
- }
-
- // these should be last
- if ("description".equals(name)) {
- return -10;
- } else if ("id".equals(name)) {
- return -9;
- } else if ("pattern".equals(name) && "to".equals(model.getName())) {
- // and pattern only for the to model
- return -8;
- }
- return 0;
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/8a18e284/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 79bf935..ffeb73b 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
@@ -24,6 +24,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
@@ -52,6 +53,14 @@ import org.apache.camel.tools.apt.model.ComponentOption;
import org.apache.camel.tools.apt.model.EndpointOption;
import org.apache.camel.tools.apt.model.EndpointPath;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.dumpExceptionToErrorFile;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findFieldElement;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findJavaDoc;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.findTypeElement;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.implementsInterface;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.loadResource;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.processFile;
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.warning;
import static org.apache.camel.tools.apt.helper.JsonSchemaHelper.sanitizeDescription;
import static org.apache.camel.tools.apt.helper.Strings.canonicalClassName;
import static org.apache.camel.tools.apt.helper.Strings.getOrElse;
@@ -63,7 +72,7 @@ import static org.apache.camel.tools.apt.helper.Strings.safeNull;
*/
@SupportedAnnotationTypes({"org.apache.camel.spi.*"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
-public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
+public class EndpointAnnotationProcessor extends AbstractProcessor {
// CHECKSTYLE:OFF
@@ -114,7 +123,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
return null;
}
};
- processFile(packageName, fileName, handler);
+ processFile(processingEnv, packageName, fileName, handler);
// write json schema
fileName = alias + ".json";
@@ -125,7 +134,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
return null;
}
};
- processFile(packageName, fileName, handler);
+ processFile(processingEnv, packageName, fileName, handler);
}
}
}
@@ -177,7 +186,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
String consumerPrefix = getOrElse(uriEndpoint.consumerPrefix(), "");
if (consumerType != null) {
consumerClassName = consumerType.toString();
- TypeElement consumerElement = findTypeElement(roundEnv, consumerClassName);
+ TypeElement consumerElement = findTypeElement(processingEnv, roundEnv, consumerClassName);
if (consumerElement != null) {
writer.println("<h2>" + scheme + " consumer" + "</h2>");
writeHtmlDocumentationAndFieldInjections(writer, roundEnv, componentModel, consumerElement, consumerPrefix, uriEndpoint.excludeProperties());
@@ -185,7 +194,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
}
}
if (!found && consumerClassName != null) {
- warning("APT could not find consumer class " + consumerClassName);
+ warning(processingEnv, "APT could not find consumer class " + consumerClassName);
}
writer.println("</body>");
writer.println("</html>");
@@ -201,7 +210,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
Set<EndpointOption> endpointOptions = new LinkedHashSet<EndpointOption>();
Set<ComponentOption> componentOptions = new LinkedHashSet<ComponentOption>();
- TypeElement componentClassElement = findTypeElement(roundEnv, componentModel.getJavaType());
+ TypeElement componentClassElement = findTypeElement(processingEnv, roundEnv, componentModel.getJavaType());
if (componentClassElement != null) {
findComponentClassProperties(writer, roundEnv, componentModel, componentOptions, componentClassElement, "");
}
@@ -462,15 +471,15 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
model.setConsumerOnly(uriEndpoint.consumerOnly());
model.setProducerOnly(uriEndpoint.producerOnly());
model.setLenientProperties(uriEndpoint.lenientProperties());
- model.setAsync(implementsInterface(roundEnv, endpointClassElement, "org.apache.camel.AsyncEndpoint"));
+ model.setAsync(implementsInterface(processingEnv, roundEnv, endpointClassElement, "org.apache.camel.AsyncEndpoint"));
- String data = loadResource("META-INF/services/org/apache/camel/component", scheme);
+ String data = loadResource(processingEnv, "META-INF/services/org/apache/camel/component", scheme);
if (data != null) {
Map<String, String> map = parseAsMap(data);
model.setJavaType(map.get("class"));
}
- data = loadResource("META-INF/services/org/apache/camel", "component.properties");
+ data = loadResource(processingEnv, "META-INF/services/org/apache/camel", "component.properties");
if (data != null) {
Map<String, String> map = parseAsMap(data);
// now we have a lot more data, so we need to load it as key/value
@@ -510,7 +519,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
// favor to use endpoint class javadoc as description
Elements elementUtils = processingEnv.getElementUtils();
- TypeElement typeElement = findTypeElement(roundEnv, endpointClassElement.getQualifiedName().toString());
+ TypeElement typeElement = findTypeElement(processingEnv, roundEnv, endpointClassElement.getQualifiedName().toString());
if (typeElement != null) {
String doc = elementUtils.getDocComment(typeElement);
if (doc != null) {
@@ -571,7 +580,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
name = prefix + name;
TypeMirror fieldType = setter.getParameters().get(0).asType();
String fieldTypeName = fieldType.toString();
- TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
+ TypeElement fieldTypeElement = findTypeElement(processingEnv, roundEnv, fieldTypeName);
String docComment = findJavaDoc(elementUtils, method, fieldName, name, classElement, false);
if (isNullOrEmpty(docComment)) {
@@ -590,7 +599,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
Set<String> enums = new LinkedHashSet<String>();
boolean isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
if (isEnum) {
- TypeElement enumClass = findTypeElement(roundEnv, fieldTypeElement.asType().toString());
+ TypeElement enumClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString());
// find all the enum constants which has the possible enum value that can be used
List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
for (VariableElement var : fields) {
@@ -612,7 +621,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
TypeMirror superclass = classElement.getSuperclass();
if (superclass != null) {
String superClassName = canonicalClassName(superclass.toString());
- baseTypeElement = findTypeElement(roundEnv, superClassName);
+ baseTypeElement = findTypeElement(processingEnv, roundEnv, superClassName);
}
if (baseTypeElement != null) {
classElement = baseTypeElement;
@@ -661,7 +670,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
TypeMirror fieldType = fieldElement.asType();
String fieldTypeName = fieldType.toString();
- TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
+ TypeElement fieldTypeElement = findTypeElement(processingEnv, roundEnv, fieldTypeName);
String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, name, classElement, false);
if (isNullOrEmpty(docComment)) {
@@ -681,7 +690,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
} else {
isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
if (isEnum) {
- TypeElement enumClass = findTypeElement(roundEnv, fieldTypeElement.asType().toString());
+ TypeElement enumClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString());
// find all the enum constants which has the possible enum value that can be used
List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
for (VariableElement var : fields) {
@@ -735,7 +744,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
// if the field type is a nested parameter then iterate through its fields
TypeMirror fieldType = fieldElement.asType();
String fieldTypeName = fieldType.toString();
- TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName);
+ TypeElement fieldTypeElement = findTypeElement(processingEnv, roundEnv, fieldTypeName);
UriParams fieldParams = null;
if (fieldTypeElement != null) {
fieldParams = fieldTypeElement.getAnnotation(UriParams.class);
@@ -769,7 +778,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
} else {
isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM;
if (isEnum) {
- TypeElement enumClass = findTypeElement(roundEnv, fieldTypeElement.asType().toString());
+ TypeElement enumClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString());
// find all the enum constants which has the possible enum value that can be used
List<VariableElement> fields = ElementFilter.fieldsIn(enumClass.getEnclosedElements());
for (VariableElement var : fields) {
@@ -800,7 +809,7 @@ public class EndpointAnnotationProcessor extends AbstractAnnotationProcessor {
TypeMirror superclass = classElement.getSuperclass();
if (superclass != null) {
String superClassName = canonicalClassName(superclass.toString());
- baseTypeElement = findTypeElement(roundEnv, superClassName);
+ baseTypeElement = findTypeElement(processingEnv, roundEnv, superClassName);
}
if (baseTypeElement != null) {
classElement = baseTypeElement;
http://git-wip-us.apache.org/repos/asf/camel/blob/8a18e284/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelAnnotationProcessor.java
new file mode 100644
index 0000000..c56fafc
--- /dev/null
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelAnnotationProcessor.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.tools.apt;
+
+import java.util.Set;
+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.Element;
+import javax.lang.model.element.TypeElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import static org.apache.camel.tools.apt.AnnotationProcessorHelper.dumpExceptionToErrorFile;
+import static org.apache.camel.tools.apt.helper.Strings.canonicalClassName;
+
+/**
+ * APT compiler plugin to generate JSon Schema for all EIP models and camel-spring's <camelContext> types.
+ */
+@SupportedAnnotationTypes({"javax.xml.bind.annotation.*", "org.apache.camel.spi.Label"})
+@SupportedSourceVersion(SourceVersion.RELEASE_8)
+public class ModelAnnotationProcessor extends AbstractProcessor {
+
+ CoreEipAnnotationProcessor coreProcessor = new CoreEipAnnotationProcessor();
+ SpringAnnotationProcessor springProcessor = new SpringAnnotationProcessor();
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ try {
+ if (roundEnv.processingOver()) {
+ return true;
+ }
+
+ Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(XmlRootElement.class);
+ for (Element element : elements) {
+ if (element instanceof TypeElement) {
+ TypeElement classElement = (TypeElement) element;
+
+ final String javaTypeName = canonicalClassName(classElement.getQualifiedName().toString());
+ boolean core = javaTypeName.startsWith("org.apache.camel.model");
+ boolean spring = javaTypeName.startsWith("org.apache.camel.spring") || javaTypeName.startsWith("org.apache.camel.core.xml");
+ if (core) {
+ coreProcessor.processModelClass(processingEnv, roundEnv, classElement);
+ } else if (spring) {
+ springProcessor.processModelClass(processingEnv, roundEnv, classElement);
+ }
+ }
+ }
+ } catch (Throwable e) {
+ dumpExceptionToErrorFile("camel-apt-error.log", "Error processing", e);
+ }
+
+ return true;
+ }
+
+}
\ No newline at end of file