package com.stanfy.enroscar.async.internal;
import com.squareup.javawriter.JavaWriter;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
import static javax.tools.Diagnostic.Kind.ERROR;
/**
* Base class for generators.
*/
abstract class BaseGenerator {
/** Environment. */
private final ProcessingEnvironment env;
/** Class name. */
final String className;
/** Package name. */
final String packageName;
/** Base class. */
final TypeElement operationsClass;
/** Methods. */
final List<MethodData> methods;
/** Imports to emit. */
private final Set<String> imports = new HashSet<>();
/** Loader IDs. */
private static final HashMap<ExecutableElement, Integer> LOADER_IDS = new HashMap<>();
/** What we extend. */
private String extendsClass;
public BaseGenerator(final ProcessingEnvironment env, final TypeElement type,
final List<MethodData> methods, final String suffix) {
this.env = env;
this.operationsClass = type;
this.packageName = env.getElementUtils().getPackageOf(type).getQualifiedName().toString();
this.className = GenUtils.getGeneratedClassName(packageName, type.getQualifiedName().toString(), suffix);
this.methods = methods;
}
public String getFqcn() {
if (packageName.length() == 0) {
return className;
}
return packageName + "." + className;
}
protected final void addImports(final String... imports) {
this.imports.addAll(Arrays.asList(imports));
}
protected final void addImports(final Collection<String> imports) {
this.imports.addAll(imports);
}
protected final void setExtendsClass(final String name) {
this.extendsClass = name;
}
protected final int getLoaderId(final ExecutableElement method) {
Integer res = LOADER_IDS.get(method);
if (res == null) {
res = GenUtils.nextLoaderId();
LOADER_IDS.put(method, res);
}
return res;
}
public final void generateCode() {
Writer out = null;
try {
JavaFileObject jfo = env.getFiler().createSourceFile(getFqcn(), operationsClass);
out = jfo.openWriter();
GenUtils.generate(this, out);
out.flush();
} catch (IOException e) {
env.getMessager().printMessage(
ERROR,
"Cannot generate loader for base class " + operationsClass + ": " + e.getMessage(),
operationsClass
);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
// nothing
}
}
}
}
final void generateTo(final Writer out) throws IOException {
JavaWriter w = new JavaWriter(out);
w.emitSingleLineComment("Code generated by Enroscar. Do not edit. %s",
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).format(new Date()));
w.emitPackage(packageName);
w.emitImports(imports);
w.emitEmptyLine();
classJavaDoc(w);
w.beginType(className, "class", modifiers(operationsClass), extendsClass);
w.emitEmptyLine();
writeClassBody(w);
w.endType();
}
protected void classJavaDoc(final JavaWriter w) throws IOException {
// nothing
}
protected abstract void writeClassBody(final JavaWriter w) throws IOException;
private static Set<Modifier> modifiers(final Element e) {
Set<Modifier> modifiers = e.getModifiers();
if (modifiers instanceof EnumSet) {
return modifiers;
}
if (modifiers.isEmpty()) {
return EnumSet.noneOf(Modifier.class);
}
final EnumSet<Modifier> resultSet = EnumSet.copyOf(modifiers);
resultSet.remove(STATIC);
return resultSet;
}
protected Set<Modifier> constructorModifiers() {
Set<Modifier> m = modifiers(operationsClass);
return m.contains(PUBLIC) ? EnumSet.of(PUBLIC) : EnumSet.noneOf(Modifier.class);
}
}