package io.vertx.codegen;

import io.vertx.codegen.annotations.*;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.*;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import java.io.File;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
 */
@SupportedAnnotationTypes({"io.vertx.codegen.annotations.VertxGen"})
@javax.annotation.processing.SupportedOptions({"fileExtension", "outputLocation", "templateFileName"})
@javax.annotation.processing.SupportedSourceVersion(javax.lang.model.SourceVersion.RELEASE_8)
public class CodeGenProcessor extends AbstractProcessor {

  private static final Logger log = Logger.getLogger(CodeGenProcessor.class.getName());
  private Elements elementUtils;
  private Types typeUtils;
  private String fileExtension;
  private String outputLocation;
  private String templateFileName;

  @Override
  public synchronized void init(ProcessingEnvironment env) {
    super.init(env);
    fileExtension = env.getOptions().get("fileExtension");
    outputLocation = env.getOptions().get("outputLocation");
    templateFileName = env.getOptions().get("templateFileName");
    elementUtils = env.getElementUtils();
    typeUtils = env.getTypeUtils();
  }

  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    if (!roundEnv.errorRaised()) {
      if (!roundEnv.processingOver()) {
        for (Element genElt : roundEnv.getElementsAnnotatedWith(VertxGen.class)) {
          String pkgName = elementUtils.getPackageOf(genElt).getQualifiedName().toString();
          if (!pkgName.contains("impl")) {
            try {
              Generator generator = new Generator();
              generator.traverseElem(elementUtils, typeUtils, genElt);
              if (outputLocation != null && templateFileName != null) {
                String target = outputLocation + File.separator + Helper.convertCamelCaseToUnderscores(genElt.getSimpleName().toString()) + fileExtension;
                generator.applyTemplate(target, templateFileName);
                log.info("Generated model for class " + genElt);
              } else {
                log.info("Validated model for class " + genElt);
              }
            } catch (GenException e) {
              String msg = "Could not generate model for class " + e.element + ": " + e.msg;
              log.log(Level.SEVERE, msg, e);
              processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e.element);
              break;
            } catch (Exception e) {
              String msg = "Could not generate element " + genElt;
              log.log(Level.SEVERE, msg, e);
              processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, genElt);
              break;
            }
          }
        }
      }
    }
    return true;
  }
}

@@ -58,16 +58,60 @@
 tions.*;
+%0Aimport org.mvel2.templates.TemplateRuntime;
 %0A%0Aimport
@@ -492,16 +492,64 @@
 o.File;%0A
+import java.util.HashMap;%0Aimport java.util.Map;%0A
 import j
@@ -823,58 +823,39 @@
 s(%7B%22
-fileExtension%22, %22outputLocation%22, %22templateFileNam
+templateFileName%22, %22nameTemplat
 e%22%7D)
@@ -1160,73 +1160,8 @@
 ls;%0A
-  private String fileExtension;%0A  private String outputLocation;%0A
   pr
@@ -1190,16 +1190,47 @@
 ileName;
+%0A  private String nameTemplate;
 %0A%0A  @Ove
@@ -1321,128 +1321,8 @@
 v);%0A
-    fileExtension = env.getOptions().get(%22fileExtension%22);%0A    outputLocation = env.getOptions().get(%22outputLocation%22);%0A
     
@@ -1382,16 +1382,73 @@
 Name%22);%0A
+    nameTemplate = env.getOptions().get(%22nameTemplate%22);%0A
     elem
@@ -2081,30 +2081,28 @@
     if (
-outputLocation
+nameTemplate
  != null
@@ -2153,145 +2153,368 @@
     
+Map%3C
 String
- target = outputLocation + File.separator + Helper.convertCamelCaseToUnderscores(genElt.getSimpleName().toString()) + fileExtension
+, Object%3E vars = new HashMap%3C%3E();%0A                vars.put(%22helper%22, new Helper());%0A                vars.put(%22fileSeparator%22, File.separator);%0A                vars.put(%22typeSimpleName%22, genElt.getSimpleName());%0A                vars.put(%22typeFQN%22, genElt.toString());%0A                String target = TemplateRuntime.eval(nameTemplate, vars).toString()
 ;%0A  

Use an mvel template for generated file names