Repository: camel Updated Branches: refs/heads/master 4c130488c -> 92a351e34
CAMEL-7999: apt compiler to generate json schema documentation for the model, whcih we later use to enrich the xml xsd to include documentation. Work in progress. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/e5bdc179 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/e5bdc179 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/e5bdc179 Branch: refs/heads/master Commit: e5bdc179bf7887dff79f814f91791c1a9bb593b9 Parents: 4c13048 Author: Claus Ibsen <davscl...@apache.org> Authored: Wed Dec 31 08:35:16 2014 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Wed Dec 31 08:35:16 2014 +0100 ---------------------------------------------------------------------- .../camel/tools/apt/EipAnnotationProcessor.java | 708 +++++++++++++++++++ .../ModelDocumentationAnnotationProcessor.java | 708 ------------------- .../javax.annotation.processing.Processor | 2 +- 3 files changed, 709 insertions(+), 709 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/e5bdc179/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 new file mode 100644 index 0000000..8805c1b --- /dev/null +++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EipAnnotationProcessor.java @@ -0,0 +1,708 @@ +/** + * 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.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.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +import org.apache.camel.spi.Label; + +import static org.apache.camel.tools.apt.JsonSchemaHelper.sanitizeDescription; +import static org.apache.camel.tools.apt.Strings.canonicalClassName; +import static org.apache.camel.tools.apt.Strings.isNullOrEmpty; +import static org.apache.camel.tools.apt.Strings.safeNull; + +// TODO: figure out a way to specify default value in the model classes which this APT can read + +// TODO: add support for @XmlElements which a few EIPs uses such as resequence +//@XmlElements({ +// @XmlElement(name = "batch-config", type = BatchResequencerConfig.class), +// @XmlElement(name = "stream-config", type = StreamResequencerConfig.class)} +//) + + +/** + * 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_7) +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 = "org.apache.camel.model.language.ExpressionDefinition"; + // 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", + }; + + private boolean skipUnwanted = true; + + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + 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); + } + } + 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); + 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 name) { + // gather eip information + EipModel eipModel = findEipModelProperties(roundEnv, classElement, javaTypeName, name); + + // get endpoint information which is divided into paths and options (though there should really only be one path) + Set<EipOption> eipOptions = new LinkedHashSet<EipOption>(); + findClassProperties(writer, roundEnv, eipOptions, classElement, classElement, ""); + + 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 \"name\": \"").append(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.isEnumType(), entry.getEnums(), entry.isOneOf(), entry.getOneOfTypes())); + } + 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); + + Label label = classElement.getAnnotation(Label.class); + if (label != null) { + model.setLabel(label.value()); + } + + // 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) { + Elements elementUtils = processingEnv.getElementUtils(); + while (true) { + List<VariableElement> fieldElements = ElementFilter.fieldsIn(classElement.getEnclosedElements()); + for (VariableElement fieldElement : fieldElements) { + + XmlAttribute attribute = fieldElement.getAnnotation(XmlAttribute.class); + String fieldName = fieldElement.getSimpleName().toString(); + if (attribute != null) { + 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)) { + continue; + } + } + + name = prefix + name; + TypeMirror fieldType = fieldElement.asType(); + String fieldTypeName = fieldType.toString(); + TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName); + + String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement, true); + boolean required = attribute.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); + } + } + } + + EipOption ep = new EipOption(name, "attribute", fieldTypeName, required, "", docComment, isEnum, enums, false, null); + eipOptions.add(ep); + } + + XmlElement element = fieldElement.getAnnotation(XmlElement.class); + fieldName = fieldElement.getSimpleName().toString(); + if (element != null) { + String kind = "element"; + String name = element.name(); + if (isNullOrEmpty(name) || "##default".equals(name)) { + name = fieldName; + } + name = prefix + name; + TypeMirror fieldType = fieldElement.asType(); + String fieldTypeName = fieldType.toString(); + TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName); + + String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement, true); + boolean required = element.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) { + TypeElement languages = findTypeElement(roundEnv, ONE_OF_LANGUAGES); + String superClassName = canonicalClassName(languages.toString()); + // find all classes that has that superClassName + Set<TypeElement> children = new LinkedHashSet<TypeElement>(); + findTypeElementChildren(roundEnv, children, superClassName); + for (TypeElement child : children) { + XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class); + if (rootElement != null) { + String childName = rootElement.name(); + if (childName != null) { + oneOfTypes.add(childName); + } + } + } + } + + EipOption ep = new EipOption(name, kind, fieldTypeName, required, "", docComment, isEnum, enums, isOneOf, oneOfTypes); + eipOptions.add(ep); + } + + // special for eips which has outputs or requires an expressions + XmlElementRef elementRef = fieldElement.getAnnotation(XmlElementRef.class); + fieldName = fieldElement.getSimpleName().toString(); + if (elementRef != null) { + + // special for outputs + processOutputs(roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix); + + // special for expression + processExpression(roundEnv, 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 void processRoute(RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement, + Set<EipOption> eipOptions, String prefix) { + + Elements elementUtils = processingEnv.getElementUtils(); + + // group + String docComment = findJavaDoc(elementUtils, null, "group", classElement, true); + EipOption ep = new EipOption("group", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // group + docComment = findJavaDoc(elementUtils, null, "streamCache", classElement, true); + ep = new EipOption("streamCache", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // trace + docComment = findJavaDoc(elementUtils, null, "trace", classElement, true); + ep = new EipOption("trace", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // trace + docComment = findJavaDoc(elementUtils, null, "messageHistory", classElement, true); + ep = new EipOption("messageHistory", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // trace + docComment = findJavaDoc(elementUtils, null, "handleFault", classElement, true); + ep = new EipOption("handleFault", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // delayer + docComment = findJavaDoc(elementUtils, null, "delayer", classElement, true); + ep = new EipOption("delayer", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // autoStartup + docComment = findJavaDoc(elementUtils, null, "autoStartup", classElement, true); + ep = new EipOption("autoStartup", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // startupOrder + docComment = findJavaDoc(elementUtils, null, "startupOrder", classElement, true); + ep = new EipOption("startupOrder", "attribute", "java.lang.Integer", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // errorHandlerRef + docComment = findJavaDoc(elementUtils, null, "errorHandlerRef", classElement, true); + ep = new EipOption("errorHandlerRef", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // routePolicyRef + docComment = findJavaDoc(elementUtils, null, "routePolicyRef", classElement, true); + ep = new EipOption("routePolicyRef", "attribute", "java.lang.String", false, "", docComment, 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", classElement, true); + ep = new EipOption("shutdownRoute", "attribute", "org.apache.camel.ShutdownRoute", false, "", docComment, true, enums, false, null); + eipOptions.add(ep); + + // shutdownRunningTask + enums = new LinkedHashSet<String>(); + enums.add("CompleteCurrentTaskOnly"); + enums.add("CompleteAllTasks"); + docComment = findJavaDoc(elementUtils, null, "shutdownRunningTask", classElement, true); + ep = new EipOption("shutdownRunningTask", "attribute", "org.apache.camel.ShutdownRunningTask", false, "", docComment, true, enums, false, null); + eipOptions.add(ep); + + // inputs + Set<String> oneOfTypes = new TreeSet<String>(); + oneOfTypes.add("from"); + docComment = findJavaDoc(elementUtils, null, "inputs", classElement, true); + ep = new EipOption("inputs", "element", "java.util.List<org.apache.camel.model.FromDefinition>", true, "", docComment, 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", classElement, true); + ep = new EipOption("outputs", "element", "java.util.List<org.apache.camel.model.ProcessorDefinition<?>>", true, "", docComment, 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", classElement, true); + EipOption ep = new EipOption("id", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + + // description + docComment = findJavaDoc(elementUtils, null, "description", classElement, true); + ep = new EipOption("description", "element", "org.apache.camel.model.DescriptionDefinition", false, "", docComment, 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", classElement, true); + ep = new EipOption("customId", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); + eipOptions.add(ep); + } + } + + /** + * Special for processing an @XmlElementRef expression field + */ + private void processExpression(RoundEnvironment roundEnv, XmlElementRef elementRef, VariableElement fieldElement, + String fieldName, Set<EipOption> eipOptions, String prefix) { + if ("expression".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(); + + // gather oneOf expression/predicates which uses language + Set<String> oneOfTypes = new TreeSet<String>(); + TypeElement languages = findTypeElement(roundEnv, ONE_OF_LANGUAGES); + String superClassName = canonicalClassName(languages.toString()); + // find all classes that has that superClassName + Set<TypeElement> children = new LinkedHashSet<TypeElement>(); + findTypeElementChildren(roundEnv, children, superClassName); + for (TypeElement child : children) { + XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class); + if (rootElement != null) { + String childName = rootElement.name(); + if (childName != null) { + oneOfTypes.add(childName); + } + } + } + + EipOption ep = new EipOption(name, kind, fieldTypeName, true, "", "", 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, 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 static final class EipModel { + + private String name; + private String javaType; + private String label; + private String description; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + 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 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 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.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 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(); + } + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/e5bdc179/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelDocumentationAnnotationProcessor.java ---------------------------------------------------------------------- diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelDocumentationAnnotationProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelDocumentationAnnotationProcessor.java deleted file mode 100644 index 7015061..0000000 --- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/ModelDocumentationAnnotationProcessor.java +++ /dev/null @@ -1,708 +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.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.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -import org.apache.camel.spi.Label; - -import static org.apache.camel.tools.apt.JsonSchemaHelper.sanitizeDescription; -import static org.apache.camel.tools.apt.Strings.canonicalClassName; -import static org.apache.camel.tools.apt.Strings.isNullOrEmpty; -import static org.apache.camel.tools.apt.Strings.safeNull; - -// TODO: figure out a way to specify default value in the model classes which this APT can read - -// TODO: add support for @XmlElements which a few EIPs uses such as resequence -//@XmlElements({ -// @XmlElement(name = "batch-config", type = BatchResequencerConfig.class), -// @XmlElement(name = "stream-config", type = StreamResequencerConfig.class)} -//) - - -/** - * 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_7) -public class ModelDocumentationAnnotationProcessor 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 = "org.apache.camel.model.language.ExpressionDefinition"; - // 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", - }; - - private boolean skipUnwanted = true; - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - 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); - } - } - 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); - 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 name) { - // gather eip information - EipModel eipModel = findEipModelProperties(roundEnv, classElement, javaTypeName, name); - - // get endpoint information which is divided into paths and options (though there should really only be one path) - Set<EipOption> eipOptions = new LinkedHashSet<EipOption>(); - findClassProperties(writer, roundEnv, eipOptions, classElement, classElement, ""); - - 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 \"name\": \"").append(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.isEnumType(), entry.getEnums(), entry.isOneOf(), entry.getOneOfTypes())); - } - 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); - - Label label = classElement.getAnnotation(Label.class); - if (label != null) { - model.setLabel(label.value()); - } - - // 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) { - Elements elementUtils = processingEnv.getElementUtils(); - while (true) { - List<VariableElement> fieldElements = ElementFilter.fieldsIn(classElement.getEnclosedElements()); - for (VariableElement fieldElement : fieldElements) { - - XmlAttribute attribute = fieldElement.getAnnotation(XmlAttribute.class); - String fieldName = fieldElement.getSimpleName().toString(); - if (attribute != null) { - 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)) { - continue; - } - } - - name = prefix + name; - TypeMirror fieldType = fieldElement.asType(); - String fieldTypeName = fieldType.toString(); - TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName); - - String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement, true); - boolean required = attribute.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); - } - } - } - - EipOption ep = new EipOption(name, "attribute", fieldTypeName, required, "", docComment, isEnum, enums, false, null); - eipOptions.add(ep); - } - - XmlElement element = fieldElement.getAnnotation(XmlElement.class); - fieldName = fieldElement.getSimpleName().toString(); - if (element != null) { - String kind = "element"; - String name = element.name(); - if (isNullOrEmpty(name) || "##default".equals(name)) { - name = fieldName; - } - name = prefix + name; - TypeMirror fieldType = fieldElement.asType(); - String fieldTypeName = fieldType.toString(); - TypeElement fieldTypeElement = findTypeElement(roundEnv, fieldTypeName); - - String docComment = findJavaDoc(elementUtils, fieldElement, fieldName, classElement, true); - boolean required = element.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) { - TypeElement languages = findTypeElement(roundEnv, ONE_OF_LANGUAGES); - String superClassName = canonicalClassName(languages.toString()); - // find all classes that has that superClassName - Set<TypeElement> children = new LinkedHashSet<TypeElement>(); - findTypeElementChildren(roundEnv, children, superClassName); - for (TypeElement child : children) { - XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class); - if (rootElement != null) { - String childName = rootElement.name(); - if (childName != null) { - oneOfTypes.add(childName); - } - } - } - } - - EipOption ep = new EipOption(name, kind, fieldTypeName, required, "", docComment, isEnum, enums, isOneOf, oneOfTypes); - eipOptions.add(ep); - } - - // special for eips which has outputs or requires an expressions - XmlElementRef elementRef = fieldElement.getAnnotation(XmlElementRef.class); - fieldName = fieldElement.getSimpleName().toString(); - if (elementRef != null) { - - // special for outputs - processOutputs(roundEnv, originalClassType, elementRef, fieldElement, fieldName, eipOptions, prefix); - - // special for expression - processExpression(roundEnv, 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 void processRoute(RoundEnvironment roundEnv, TypeElement originalClassType, TypeElement classElement, - Set<EipOption> eipOptions, String prefix) { - - Elements elementUtils = processingEnv.getElementUtils(); - - // group - String docComment = findJavaDoc(elementUtils, null, "group", classElement, true); - EipOption ep = new EipOption("group", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // group - docComment = findJavaDoc(elementUtils, null, "streamCache", classElement, true); - ep = new EipOption("streamCache", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // trace - docComment = findJavaDoc(elementUtils, null, "trace", classElement, true); - ep = new EipOption("trace", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // trace - docComment = findJavaDoc(elementUtils, null, "messageHistory", classElement, true); - ep = new EipOption("messageHistory", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // trace - docComment = findJavaDoc(elementUtils, null, "handleFault", classElement, true); - ep = new EipOption("handleFault", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // delayer - docComment = findJavaDoc(elementUtils, null, "delayer", classElement, true); - ep = new EipOption("delayer", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // autoStartup - docComment = findJavaDoc(elementUtils, null, "autoStartup", classElement, true); - ep = new EipOption("autoStartup", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // startupOrder - docComment = findJavaDoc(elementUtils, null, "startupOrder", classElement, true); - ep = new EipOption("startupOrder", "attribute", "java.lang.Integer", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // errorHandlerRef - docComment = findJavaDoc(elementUtils, null, "errorHandlerRef", classElement, true); - ep = new EipOption("errorHandlerRef", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // routePolicyRef - docComment = findJavaDoc(elementUtils, null, "routePolicyRef", classElement, true); - ep = new EipOption("routePolicyRef", "attribute", "java.lang.String", false, "", docComment, 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", classElement, true); - ep = new EipOption("shutdownRoute", "attribute", "org.apache.camel.ShutdownRoute", false, "", docComment, true, enums, false, null); - eipOptions.add(ep); - - // shutdownRunningTask - enums = new LinkedHashSet<String>(); - enums.add("CompleteCurrentTaskOnly"); - enums.add("CompleteAllTasks"); - docComment = findJavaDoc(elementUtils, null, "shutdownRunningTask", classElement, true); - ep = new EipOption("shutdownRunningTask", "attribute", "org.apache.camel.ShutdownRunningTask", false, "", docComment, true, enums, false, null); - eipOptions.add(ep); - - // inputs - Set<String> oneOfTypes = new TreeSet<String>(); - oneOfTypes.add("from"); - docComment = findJavaDoc(elementUtils, null, "inputs", classElement, true); - ep = new EipOption("inputs", "element", "java.util.List<org.apache.camel.model.FromDefinition>", true, "", docComment, 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", classElement, true); - ep = new EipOption("outputs", "element", "java.util.List<org.apache.camel.model.ProcessorDefinition<?>>", true, "", docComment, 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", classElement, true); - EipOption ep = new EipOption("id", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - - // description - docComment = findJavaDoc(elementUtils, null, "description", classElement, true); - ep = new EipOption("description", "element", "org.apache.camel.model.DescriptionDefinition", false, "", docComment, 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", classElement, true); - ep = new EipOption("customId", "attribute", "java.lang.String", false, "", docComment, false, null, false, null); - eipOptions.add(ep); - } - } - - /** - * Special for processing an @XmlElementRef expression field - */ - private void processExpression(RoundEnvironment roundEnv, XmlElementRef elementRef, VariableElement fieldElement, - String fieldName, Set<EipOption> eipOptions, String prefix) { - if ("expression".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(); - - // gather oneOf expression/predicates which uses language - Set<String> oneOfTypes = new TreeSet<String>(); - TypeElement languages = findTypeElement(roundEnv, ONE_OF_LANGUAGES); - String superClassName = canonicalClassName(languages.toString()); - // find all classes that has that superClassName - Set<TypeElement> children = new LinkedHashSet<TypeElement>(); - findTypeElementChildren(roundEnv, children, superClassName); - for (TypeElement child : children) { - XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class); - if (rootElement != null) { - String childName = rootElement.name(); - if (childName != null) { - oneOfTypes.add(childName); - } - } - } - - EipOption ep = new EipOption(name, kind, fieldTypeName, true, "", "", 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, 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 static final class EipModel { - - private String name; - private String javaType; - private String label; - private String description; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - 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 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 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.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 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(); - } - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/e5bdc179/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 68f577f..5148414 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,5 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. # +org.apache.camel.tools.apt.EipAnnotationProcessor org.apache.camel.tools.apt.EndpointAnnotationProcessor -org.apache.camel.tools.apt.ModelDocumentationAnnotationProcessor