net.zerobuilder.compiler.generate.DtoGeneratorOutput Maven / Gradle / Ivy
package net.zerobuilder.compiler.generate;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
import net.zerobuilder.compiler.generate.DtoContext.BuilderLifecycle;
import net.zerobuilder.compiler.generate.DtoModuleOutput.SimpleModuleOutput;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
import static java.util.Collections.emptyList;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
import static net.zerobuilder.compiler.generate.DtoGeneratorOutput.BuilderMethod.getMethod;
import static net.zerobuilder.compiler.generate.ZeroUtil.transform;
public final class DtoGeneratorOutput {
/**
* Can be either a {@code builder} or {@code updater} method
*/
public static final class BuilderMethod {
private final String name;
private final MethodSpec method;
public BuilderMethod(String name, MethodSpec method) {
this.name = name;
this.method = method;
}
/**
* Returns the name of the goal that generates this method.
*
* @return goal name
*/
public String name() {
return name;
}
public MethodSpec method() {
return method;
}
static final Function getMethod
= builderMethod -> builderMethod.method;
}
public static final class GeneratorOutput {
final List methods;
final List nestedTypes;
final List fields;
final ClassName generatedType;
final BuilderLifecycle lifecycle;
private GeneratorOutput(List methods, List nestedTypes, List fields,
ClassName generatedType, BuilderLifecycle lifecycle) {
this.methods = methods;
this.nestedTypes = nestedTypes;
this.fields = fields;
this.generatedType = generatedType;
this.lifecycle = lifecycle;
}
static GeneratorOutput create(List methods, List nestedTypes, List fields,
DtoContext.BuildersContext context) {
return new GeneratorOutput(methods, nestedTypes, fields, context.generatedType, context.lifecycle);
}
/**
* Create the definition of the generated class.
*
* @param generatedAnnotations annotations to add to the generated type, if any
* @return type definition
*/
public TypeSpec typeSpec(List generatedAnnotations) {
return classBuilder(generatedType)
.addFields(fields)
.addMethod(constructor())
.addMethods(transform(methods(), getMethod))
.addAnnotations(generatedAnnotations)
.addModifiers(PUBLIC, FINAL)
.addTypes(nestedTypes)
.build();
}
private MethodSpec constructor() {
return lifecycle == BuilderLifecycle.REUSE_INSTANCES ?
ZeroUtil.constructor(PRIVATE) :
constructorBuilder()
.addStatement("throw new $T($S)", UnsupportedOperationException.class, "no instances")
.addModifiers(PRIVATE)
.build();
}
/**
* All methods in the type returned by {@link #typeSpec(List)}.
* Includes static methods. Excludes constructors.
*
* @return list of methods
*/
public List methods() {
return methods;
}
/**
* Create the definition of the generated class.
*
* @return type definition
*/
public TypeSpec typeSpec() {
return typeSpec(emptyList());
}
/**
* All types that are nested directly inside the type returned by {@link #typeSpec(List)}.
* Excludes non-static inner classes, local classes and anonymous classes.
*
* @return list of types
*/
public List nestedTypes() {
return nestedTypes;
}
/**
* Class name of the type returned by {@link #typeSpec(List)}.
*
* @return class name
*/
public ClassName generatedType() {
return generatedType;
}
}
static final class SingleModuleOutputWithField {
final SimpleModuleOutput output;
final Optional field;
SingleModuleOutputWithField(SimpleModuleOutput output, Optional field) {
this.output = output;
this.field = field;
}
}
private DtoGeneratorOutput() {
throw new UnsupportedOperationException("no instances");
}
}