package io.vertx.codegen;

import io.vertx.codegen.doc.Doc;
import io.vertx.codegen.doc.Tag;
import io.vertx.codegen.doc.Text;
import io.vertx.codegen.doc.Token;
import io.vertx.codegen.type.AnnotationValueInfo;
import io.vertx.codegen.type.AnnotationValueInfoFactory;
import io.vertx.codegen.type.EnumTypeInfo;
import io.vertx.codegen.type.TypeMirrorFactory;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

A processed enum.
Author:Julien Viet
/** * A processed enum. * * @author <a href="mailto:julien@julienviet.com">Julien Viet</a> */
public class EnumModel implements Model { private final Doc.Factory docFactory; protected final Elements elementUtils; protected final Types typeUtils; protected final TypeElement modelElt; protected EnumTypeInfo type; private final AnnotationValueInfoFactory annotationValueInfoFactory; private Doc doc; private List<EnumValueInfo> values; private List<AnnotationValueInfo> annotations; private boolean processed; private boolean deprecated; private Text deprecatedDesc; public EnumModel(ProcessingEnvironment env, TypeElement modelElt) { this.typeUtils = env.getTypeUtils(); this.elementUtils = env.getElementUtils(); this.docFactory = new Doc.Factory(env.getMessager(), elementUtils, typeUtils, new TypeMirrorFactory(elementUtils, typeUtils), modelElt); this.modelElt = modelElt; this.annotationValueInfoFactory = new AnnotationValueInfoFactory(new TypeMirrorFactory(elementUtils, typeUtils)); this.deprecated = modelElt.getAnnotation(Deprecated.class) != null; } public boolean process() { if (!processed) { if (modelElt.getKind() != ElementKind.ENUM) { throw new GenException(modelElt, "@VertxGen can only be used with interfaces or enums" + modelElt.asType().toString()); } doc = docFactory.createDoc(modelElt); if (doc != null) { doc.getBlockTags().stream().filter(tag -> tag.getName().equals("deprecated")).findFirst().ifPresent(tag -> deprecatedDesc = new Text(Helper.normalizeWhitespaces(tag.getValue())).map(Token.tagMapper(elementUtils, typeUtils, modelElt)) ); } type = (EnumTypeInfo) new TypeMirrorFactory(elementUtils, typeUtils).create(modelElt.asType()); Helper.checkUnderModule(this, "@VertxGen"); values = elementUtils. getAllMembers(modelElt). stream(). filter(elt -> elt.getKind() == ElementKind.ENUM_CONSTANT). flatMap(Helper.cast(VariableElement.class)). map(elt -> { Doc doc = docFactory.createDoc(elt); Text enumItemDeprecatedDesc = null; if (doc != null) { Optional<Tag> methodDeprecatedTag = doc. getBlockTags(). stream(). filter(tag -> tag.getName().equals("deprecated")). findFirst(); if (methodDeprecatedTag.isPresent()) { enumItemDeprecatedDesc = new Text(Helper.normalizeWhitespaces(methodDeprecatedTag.get().getValue())).map(Token.tagMapper(elementUtils, typeUtils, modelElt)); } } return new EnumValueInfo(elt.getSimpleName().toString(), doc, elt.getAnnotation(Deprecated.class) != null, enumItemDeprecatedDesc); }). collect(Collectors.toList()); if (values.isEmpty()) { throw new GenException(modelElt, "No empty enums"); } processed = true; return true; } else { return false; } } private void processTypeAnnotations() { this.annotations = elementUtils.getAllAnnotationMirrors(modelElt).stream().map(annotationValueInfoFactory::processAnnotation).collect(Collectors.toList()); }
Returns:the type of this enum model
/** * @return the type of this enum model */
public EnumTypeInfo getType() { return type; }
Returns:the possible enum values
/** * @return the possible enum values */
public List<EnumValueInfo> getValues() { return values; }
Returns:the enum doc
/** * @return the enum doc */
public Doc getDoc() { return doc; } @Override public String getKind() { return "enum"; } @Override public Element getElement() { return modelElt; } @Override public String getFqn() { return modelElt.getQualifiedName().toString(); }
Returns:true if the class has a @Deprecated annotation
/** * @return {@code true} if the class has a {@code @Deprecated} annotation */
public boolean isDeprecated() { return deprecated; }
Returns:the description of deprecated
/** * @return the description of deprecated */
public Text getDeprecatedDesc() { return deprecatedDesc; } @Override public Map<String, Object> getVars() { Map<String, Object> vars = Model.super.getVars(); vars.put("type", getType()); vars.put("doc", doc); vars.put("values", values); vars.put("deprecated", deprecated); vars.put("deprecatedDesc", getDeprecatedDesc()); return vars; } @Override public ModuleInfo getModule() { return type.getModule(); } }