| /* |
| * 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 java.util.stream.Collectors; |
| |
| 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.AsPredicate; |
| 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.implementsInterface; |
| 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 and for some models java source code is generated |
| * which allows for faster property placeholder resolution at runtime; without the |
| * overhead of using reflections. |
| */ |
| public class CoreEipAnnotationProcessorHelper { |
| |
| // 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 - and not in particular if they support outputs or not) |
| 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.OutputExpressionNode", |
| "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, Set<String> propertyPlaceholderDefinitions) { |
| 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 and property placeholder provider |
| processFile(processingEnv, packageName, fileName, writer -> writeJSonSchemeAndPropertyPlaceholderProvider(processingEnv, writer, |
| roundEnv, classElement, rootElement, javaTypeName, name, propertyPlaceholderDefinitions)); |
| } |
| |
| protected void writeJSonSchemeAndPropertyPlaceholderProvider(ProcessingEnvironment processingEnv, PrintWriter writer, RoundEnvironment roundEnv, TypeElement classElement, |
| XmlRootElement rootElement, String javaTypeName, String modelName, Set<String> propertyPlaceholderDefinitions) { |
| // 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<>(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)); |
| |
| // write json schema file |
| String json = createParameterJsonSchema(eipModel, eipOptions); |
| writer.println(json); |
| |
| // generate property placeholder provider java source code |
| generatePropertyPlaceholderProviderSource(processingEnv, writer, roundEnv, classElement, eipModel, eipOptions, propertyPlaceholderDefinitions); |
| } |
| |
| protected void generatePropertyPlaceholderProviderSource(ProcessingEnvironment processingEnv, PrintWriter writer, RoundEnvironment roundEnv, TypeElement classElement, |
| EipModel eipModel, Set<EipOption> options, Set<String> propertyPlaceholderDefinitions) { |
| |
| // not ever model classes support property placeholders as this has been limited to mainly Camel routes |
| // so filter out unwanted models |
| boolean rest = classElement.getQualifiedName().toString().startsWith("org.apache.camel.model.rest"); |
| boolean processor = hasSuperClass(processingEnv, roundEnv, classElement, "org.apache.camel.model.ProcessorDefinition"); |
| boolean language = hasSuperClass(processingEnv, roundEnv, classElement, "org.apache.camel.model.language.ExpressionDefinition"); |
| boolean dataformat = hasSuperClass(processingEnv, roundEnv, classElement, "org.apache.camel.model.DataFormatDefinition"); |
| |
| if (!rest && !processor && !language && !dataformat) { |
| return; |
| } |
| |
| TypeElement parent = findTypeElement(processingEnv, roundEnv, "org.apache.camel.spi.PropertyPlaceholderConfigurer"); |
| String def = classElement.getSimpleName().toString(); |
| String fqnDef = classElement.getQualifiedName().toString(); |
| String cn = def + "PropertyPlaceholderProvider"; |
| String fqn = "org.apache.camel.model.placeholder." + cn; |
| |
| PropertyPlaceholderGenerator.generatePropertyPlaceholderProviderSource(processingEnv, parent, def, fqnDef, cn, fqn, options); |
| propertyPlaceholderDefinitions.add(fqnDef); |
| |
| // we also need to generate from when we generate route as from can also configure property placeholders |
| if ("RouteDefinition".equals(def)) { |
| def = "FromDefinition"; |
| fqnDef = "org.apache.camel.model.FromDefinition"; |
| cn = "FromDefinitionPropertyPlaceholderProvider"; |
| fqn = "org.apache.camel.model.placeholder.FromDefinitionPropertyPlaceholderProvider"; |
| |
| options.clear(); |
| options.add(new EipOption("id", null, null, "java.lang.String", false, null, null, false, null, false, null, false, null, false)); |
| options.add(new EipOption("uri", null, null, "java.lang.String", false, null, null, false, null, false, null, false, null, false)); |
| |
| PropertyPlaceholderGenerator.generatePropertyPlaceholderProviderSource(processingEnv, parent, def, fqnDef, cn, fqn, options); |
| propertyPlaceholderDefinitions.add(fqnDef); |
| } |
| } |
| |
| 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("\","); |
| if (eipModel.getFirstVersion() != null) { |
| buffer.append("\n \"firstVersion\": \"").append(safeNull(eipModel.getFirstVersion())).append("\","); |
| } |
| buffer.append("\n \"javaType\": \"").append(eipModel.getJavaType()).append("\","); |
| buffer.append("\n \"label\": \"").append(safeNull(eipModel.getLabel())).append("\","); |
| buffer.append("\n \"deprecated\": ").append(eipModel.isDeprecated()).append(","); |
| if (eipModel.getDeprecationNote() != null) { |
| buffer.append("\n \"deprecationNote\": \"").append(safeNull(eipModel.getDeprecationNote())).append("\","); |
| } |
| buffer.append("\n \"input\": ").append(eipModel.getInput()).append(","); |
| buffer.append("\n \"output\": ").append(eipModel.getOutput()); |
| buffer.append("\n },"); |
| |
| buffer.append("\n \"properties\": {"); |
| boolean first = true; |
| |
| if ("false".equals(eipModel.getOutput())) { |
| // filter out outputs if we do not support it (and preserve order so |
| // we need to use linked hash-set) |
| options = options.stream().filter(o -> !"outputs".equals(o.getName())).collect(Collectors.toCollection(LinkedHashSet::new)); |
| } |
| |
| 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.getDisplayName(), entry.getKind(), entry.isRequired(), entry.getType(), entry.getDefaultValue(), doc, |
| entry.isDeprecated(), entry.getDeprecationNote(), false, null, null, entry.isEnumType(), entry.getEnums(), entry.isOneOf(), |
| entry.getOneOfTypes(), entry.isAsPredicate(), null, null, false, null, null)); |
| } |
| 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); |
| |
| boolean deprecated = classElement.getAnnotation(Deprecated.class) != null; |
| model.setDeprecated(deprecated); |
| |
| 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()); |
| } |
| if (!Strings.isNullOrEmpty(metadata.firstVersion())) { |
| model.setFirstVersion(metadata.firstVersion()); |
| } |
| } |
| |
| // 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; |
| } |
| } |
| |
| Metadata metadata = fieldElement.getAnnotation(Metadata.class); |
| |
| name = prefix + name; |
| TypeMirror fieldType = fieldElement.asType(); |
| String fieldTypeName = fieldType.toString(); |
| TypeElement fieldTypeElement = findTypeElement(processingEnv, roundEnv, fieldTypeName); |
| if (metadata != null && !Strings.isNullOrEmpty(metadata.javaType())) { |
| fieldTypeName = metadata.javaType(); |
| } |
| |
| 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<>(); |
| boolean isEnum; |
| if (metadata != null && !Strings.isNullOrEmpty(metadata.enums())) { |
| isEnum = true; |
| String[] values = metadata.enums().split(","); |
| for (String val : values) { |
| enums.add(val); |
| } |
| } else { |
| isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM; |
| if (isEnum) { |
| TypeElement enumClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString()); |
| if (enumClass != null) { |
| // 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); |
| } |
| } |
| } |
| } |
| } |
| |
| String displayName = null; |
| if (metadata != null) { |
| displayName = metadata.displayName(); |
| } |
| boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null; |
| String deprecationNote = null; |
| if (metadata != null) { |
| deprecationNote = metadata.deprecationNote(); |
| } |
| |
| EipOption ep = new EipOption(name, displayName, "attribute", fieldTypeName, required, defaultValue, docComment, deprecated, deprecationNote, isEnum, enums, false, null, |
| false); |
| 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); |
| |
| String displayName = null; |
| Metadata metadata = fieldElement.getAnnotation(Metadata.class); |
| if (metadata != null) { |
| displayName = metadata.displayName(); |
| } |
| boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null; |
| String deprecationNote = null; |
| if (metadata != null) { |
| deprecationNote = metadata.deprecationNote(); |
| } |
| |
| EipOption ep = new EipOption(name, displayName, "value", fieldTypeName, required, defaultValue, docComment, deprecated, deprecationNote, false, null, false, null, false); |
| 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) { |
| |
| Metadata metadata = fieldElement.getAnnotation(Metadata.class); |
| |
| 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); |
| |
| // is it used as predicate (check field first and then fallback to |
| // its class) |
| boolean asPredicate = fieldElement.getAnnotation(AsPredicate.class) != null; |
| if (!asPredicate) { |
| asPredicate = classElement.getAnnotation(AsPredicate.class) != null; |
| } |
| |
| // gather enums |
| Set<String> enums = new TreeSet<>(); |
| boolean isEnum; |
| if (metadata != null && !Strings.isNullOrEmpty(metadata.enums())) { |
| isEnum = true; |
| String[] values = metadata.enums().split(","); |
| for (String val : values) { |
| enums.add(val); |
| } |
| } else { |
| isEnum = fieldTypeElement != null && fieldTypeElement.getKind() == ElementKind.ENUM; |
| if (isEnum) { |
| TypeElement enumClass = findTypeElement(processingEnv, roundEnv, fieldTypeElement.asType().toString()); |
| if (enumClass != null) { |
| // 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<>(); |
| 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); |
| if (languages != null) { |
| String superClassName = canonicalClassName(languages.toString()); |
| // find all classes that has that superClassName |
| Set<TypeElement> children = new LinkedHashSet<>(); |
| findTypeElementChildren(processingEnv, roundEnv, children, superClassName); |
| for (TypeElement child : children) { |
| XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class); |
| if (rootElement != null) { |
| String childName = rootElement.name(); |
| oneOfTypes.add(childName); |
| } |
| } |
| } |
| } |
| } |
| // special for otherwise as we want to indicate that the element is |
| if ("otherwise".equals(name)) { |
| isOneOf = true; |
| oneOfTypes.add("otherwise"); |
| } |
| |
| String displayName = null; |
| if (metadata != null) { |
| displayName = metadata.displayName(); |
| } |
| boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null; |
| String deprecationNote = null; |
| if (metadata != null) { |
| deprecationNote = metadata.deprecationNote(); |
| } |
| |
| EipOption ep = new EipOption(name, displayName, kind, fieldTypeName, required, defaultValue, docComment, deprecated, deprecationNote, isEnum, enums, isOneOf, |
| oneOfTypes, asPredicate); |
| 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<>(); |
| for (XmlElement element : elements.value()) { |
| String child = element.name(); |
| oneOfTypes.add(child); |
| } |
| |
| String displayName = null; |
| Metadata metadata = fieldElement.getAnnotation(Metadata.class); |
| if (metadata != null) { |
| displayName = metadata.displayName(); |
| } |
| boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null; |
| String deprecationNote = null; |
| if (metadata != null) { |
| deprecationNote = metadata.deprecationNote(); |
| } |
| |
| EipOption ep = new EipOption(name, displayName, kind, fieldTypeName, required, defaultValue, docComment, deprecated, deprecationNote, false, null, true, oneOfTypes, |
| false); |
| 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", "Group", "attribute", "java.lang.String", false, "", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // group |
| docComment = findJavaDoc(elementUtils, null, "streamCache", null, classElement, true); |
| ep = new EipOption("streamCache", "Stream Cache", "attribute", "java.lang.String", false, "", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // trace |
| docComment = findJavaDoc(elementUtils, null, "trace", null, classElement, true); |
| ep = new EipOption("trace", "Trace", "attribute", "java.lang.String", false, "", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // message history |
| docComment = findJavaDoc(elementUtils, null, "messageHistory", null, classElement, true); |
| ep = new EipOption("messageHistory", "Message History", "attribute", "java.lang.String", false, "true", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // log mask |
| docComment = findJavaDoc(elementUtils, null, "logMask", null, classElement, true); |
| ep = new EipOption("logMask", "Log Mask", "attribute", "java.lang.String", false, "false", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // delayer |
| docComment = findJavaDoc(elementUtils, null, "delayer", null, classElement, true); |
| ep = new EipOption("delayer", "Delayer", "attribute", "java.lang.String", false, "", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // autoStartup |
| docComment = findJavaDoc(elementUtils, null, "autoStartup", null, classElement, true); |
| ep = new EipOption("autoStartup", "Auto Startup", "attribute", "java.lang.String", false, "true", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // startupOrder |
| docComment = findJavaDoc(elementUtils, null, "startupOrder", null, classElement, true); |
| ep = new EipOption("startupOrder", "Startup Order", "attribute", "java.lang.Integer", false, "", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // errorHandlerRef |
| docComment = findJavaDoc(elementUtils, null, "errorHandlerRef", null, classElement, true); |
| ep = new EipOption("errorHandlerRef", "Error Handler", "attribute", "java.lang.String", false, "", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // routePolicyRef |
| docComment = findJavaDoc(elementUtils, null, "routePolicyRef", null, classElement, true); |
| ep = new EipOption("routePolicyRef", "Route Policy", "attribute", "java.lang.String", false, "", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // shutdownRoute |
| Set<String> enums = new LinkedHashSet<>(); |
| enums.add("Default"); |
| enums.add("Defer"); |
| docComment = findJavaDoc(elementUtils, null, "shutdownRoute", "Default", classElement, true); |
| ep = new EipOption("shutdownRoute", "Shutdown Route", "attribute", "org.apache.camel.ShutdownRoute", false, "", docComment, false, null, true, enums, false, null, false); |
| eipOptions.add(ep); |
| |
| // shutdownRunningTask |
| enums = new LinkedHashSet<>(); |
| enums.add("CompleteCurrentTaskOnly"); |
| enums.add("CompleteAllTasks"); |
| docComment = findJavaDoc(elementUtils, null, "shutdownRunningTask", "CompleteCurrentTaskOnly", classElement, true); |
| ep = new EipOption("shutdownRunningTask", "Shutdown Running Task", "attribute", "org.apache.camel.ShutdownRunningTask", false, "", docComment, false, null, true, enums, |
| false, null, false); |
| eipOptions.add(ep); |
| |
| // input |
| Set<String> oneOfTypes = new TreeSet<>(); |
| oneOfTypes.add("from"); |
| docComment = findJavaDoc(elementUtils, null, "input", null, classElement, true); |
| ep = new EipOption("input", "Input", "element", "org.apache.camel.model.FromDefinition", true, "", docComment, false, null, false, null, true, oneOfTypes, |
| false); |
| eipOptions.add(ep); |
| |
| // outputs |
| // gather oneOf which extends any of the output base classes |
| oneOfTypes = new TreeSet<>(); |
| // find all classes that has that superClassName |
| Set<TypeElement> children = new LinkedHashSet<>(); |
| 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(); |
| 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", "Outputs", "element", "java.util.List<org.apache.camel.model.ProcessorDefinition<?>>", true, "", docComment, false, null, false, null, true, |
| oneOfTypes, false); |
| 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", "Id", "attribute", "java.lang.String", false, "", docComment, false, null, false, null, false, null, false); |
| eipOptions.add(ep); |
| |
| // description |
| docComment = findJavaDoc(elementUtils, null, "description", null, classElement, true); |
| ep = new EipOption("description", "Description", "element", "org.apache.camel.model.DescriptionDefinition", false, "", docComment, false, null, false, null, false, null, |
| false); |
| 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", "Custom Id", "attribute", "java.lang.String", false, "", docComment, false, null, false, null, false, null, false); |
| 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<>(); |
| oneOfTypes.add("route"); |
| |
| EipOption ep = new EipOption("routes", "Routes", "element", fieldTypeName, false, "", "Contains the Camel routes", false, null, false, null, true, oneOfTypes, false); |
| 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<>(); |
| oneOfTypes.add("rest"); |
| |
| EipOption ep = new EipOption("rests", "Rests", "element", fieldTypeName, false, "", "Contains the rest services defined using the rest-dsl", false, null, false, null, |
| true, oneOfTypes, false); |
| 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(processingEnv, roundEnv, 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<>(); |
| // find all classes that has that superClassName |
| Set<TypeElement> children = new LinkedHashSet<>(); |
| 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(); |
| oneOfTypes.add(childName); |
| } |
| } |
| |
| // remove some types which are not intended as an output in eips |
| oneOfTypes.remove("route"); |
| String displayName = null; |
| Metadata metadata = fieldElement.getAnnotation(Metadata.class); |
| if (metadata != null) { |
| displayName = metadata.displayName(); |
| } |
| boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null; |
| String deprecationNote = null; |
| if (metadata != null) { |
| deprecationNote = metadata.deprecationNote(); |
| } |
| |
| EipOption ep = new EipOption(name, displayName, kind, fieldTypeName, true, "", "", deprecated, deprecationNote, false, null, true, oneOfTypes, false); |
| 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(processingEnv, roundEnv, 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<>(); |
| // find all classes that has that superClassName |
| Set<TypeElement> children = new LinkedHashSet<>(); |
| 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); |
| } |
| } |
| } |
| String displayName = null; |
| Metadata metadata = fieldElement.getAnnotation(Metadata.class); |
| if (metadata != null) { |
| displayName = metadata.displayName(); |
| } |
| boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null; |
| String deprecationNote = null; |
| if (metadata != null) { |
| deprecationNote = metadata.deprecationNote(); |
| } |
| |
| EipOption ep = new EipOption(name, displayName, kind, fieldTypeName, true, "", docComment, deprecated, deprecationNote, false, null, true, oneOfTypes, false); |
| 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); |
| |
| // is it used as predicate (check field first and then fallback to |
| // its class / original class) |
| boolean asPredicate = fieldElement.getAnnotation(AsPredicate.class) != null; |
| if (!asPredicate) { |
| asPredicate = classElement.getAnnotation(AsPredicate.class) != null; |
| } |
| if (!asPredicate) { |
| asPredicate = originalClassType.getAnnotation(AsPredicate.class) != null; |
| } |
| |
| // gather oneOf expression/predicates which uses language |
| Set<String> oneOfTypes = new TreeSet<>(); |
| 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<>(); |
| findTypeElementChildren(processingEnv, roundEnv, children, superClassName); |
| for (TypeElement child : children) { |
| XmlRootElement rootElement = child.getAnnotation(XmlRootElement.class); |
| if (rootElement != null) { |
| String childName = rootElement.name(); |
| oneOfTypes.add(childName); |
| } |
| } |
| } |
| |
| String displayName = null; |
| Metadata metadata = fieldElement.getAnnotation(Metadata.class); |
| if (metadata != null) { |
| displayName = metadata.displayName(); |
| } |
| boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null; |
| String deprecationNote = null; |
| if (metadata != null) { |
| deprecationNote = metadata.deprecationNote(); |
| } |
| |
| EipOption ep = new EipOption(name, displayName, kind, fieldTypeName, true, "", docComment, deprecated, deprecationNote, false, null, true, oneOfTypes, asPredicate); |
| 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); |
| |
| // indicate that this element is one of when |
| Set<String> oneOfTypes = new HashSet<>(); |
| oneOfTypes.add("when"); |
| |
| // when is predicate |
| boolean asPredicate = true; |
| |
| String displayName = null; |
| Metadata metadata = fieldElement.getAnnotation(Metadata.class); |
| if (metadata != null) { |
| displayName = metadata.displayName(); |
| } |
| boolean deprecated = fieldElement.getAnnotation(Deprecated.class) != null; |
| String deprecationNote = null; |
| if (metadata != null) { |
| deprecationNote = metadata.deprecationNote(); |
| } |
| |
| EipOption ep = new EipOption(name, displayName, kind, fieldTypeName, false, "", docComment, deprecated, deprecationNote, false, null, true, oneOfTypes, asPredicate); |
| 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(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv, TypeElement classElement) { |
| return implementsInterface(processingEnv, roundEnv, classElement, "org.apache.camel.model.OutputNode"); |
| } |
| |
| 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) { |
| return 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; |
| } |
| |
| // special for transacted/policy which should not have output |
| if ("policy".equals(model.getName()) || "transacted".equals(model.getName())) { |
| return false; |
| } |
| |
| for (EipOption option : options) { |
| if ("outputs".equals(option.getName())) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public static final class EipModel { |
| |
| private String name; |
| private String title; |
| private String javaType; |
| private String label; |
| private String description; |
| private boolean deprecated; |
| private String deprecationNote; |
| private boolean input; |
| private boolean output; |
| private String firstVersion; |
| |
| 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 isDeprecated() { |
| return deprecated; |
| } |
| |
| public void setDeprecated(boolean deprecated) { |
| this.deprecated = deprecated; |
| } |
| |
| public String getDeprecationNote() { |
| return deprecationNote; |
| } |
| |
| public void setDeprecationNote(String deprecationNote) { |
| this.deprecationNote = deprecationNote; |
| } |
| |
| 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"; |
| } |
| |
| public String getFirstVersion() { |
| return firstVersion; |
| } |
| |
| public void setFirstVersion(String firstVersion) { |
| this.firstVersion = firstVersion; |
| } |
| } |
| |
| public static final class EipOption { |
| |
| private String name; |
| private String displayName; |
| private String kind; |
| private String type; |
| private boolean required; |
| private String defaultValue; |
| private String documentation; |
| private boolean deprecated; |
| private String deprecationNote; |
| private boolean enumType; |
| private Set<String> enums; |
| private boolean oneOf; |
| private Set<String> oneOfTypes; |
| private boolean asPredicate; |
| |
| private EipOption(String name, String displayName, String kind, String type, boolean required, String defaultValue, String documentation, boolean deprecated, |
| String deprecationNote, boolean enumType, Set<String> enums, boolean oneOf, Set<String> oneOfTypes, boolean asPredicate) { |
| this.name = name; |
| this.displayName = displayName; |
| this.kind = kind; |
| this.type = type; |
| this.required = required; |
| this.defaultValue = defaultValue; |
| this.documentation = documentation; |
| this.deprecated = deprecated; |
| this.deprecationNote = deprecationNote; |
| this.enumType = enumType; |
| this.enums = enums; |
| this.oneOf = oneOf; |
| this.oneOfTypes = oneOfTypes; |
| this.asPredicate = asPredicate; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public String getDisplayName() { |
| return displayName; |
| } |
| |
| 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 String getDeprecationNote() { |
| return deprecationNote; |
| } |
| |
| public boolean isEnumType() { |
| return enumType; |
| } |
| |
| public Set<String> getEnums() { |
| return enums; |
| } |
| |
| public boolean isOneOf() { |
| return oneOf; |
| } |
| |
| public Set<String> getOneOfTypes() { |
| return oneOfTypes; |
| } |
| |
| public boolean isAsPredicate() { |
| return asPredicate; |
| } |
| |
| @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 weight = weight(o1); |
| int weight2 = weight(o2); |
| |
| if (weight == weight2) { |
| // keep the current order |
| return 1; |
| } else { |
| // sort according to weight |
| return weight2 - weight; |
| } |
| } |
| |
| private int weight(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; |
| } |
| } |
| |
| } |