net.zerobuilder.compiler.generate.DtoStep Maven / Gradle / Ivy
package net.zerobuilder.compiler.generate;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.TypeName;
import net.zerobuilder.compiler.generate.DtoBeanStep.AbstractBeanStep;
import net.zerobuilder.compiler.generate.DtoContext.BuildersContext;
import net.zerobuilder.compiler.generate.DtoGoalDetails.AbstractGoalDetails;
import net.zerobuilder.compiler.generate.DtoParameter.AbstractParameter;
import net.zerobuilder.compiler.generate.DtoRegularStep.AbstractRegularStep;
import net.zerobuilder.compiler.generate.ZeroUtil.ClassNames;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import static net.zerobuilder.compiler.generate.ZeroUtil.ClassNames.COLLECTION;
import static net.zerobuilder.compiler.generate.ZeroUtil.ClassNames.ITERABLE;
import static net.zerobuilder.compiler.generate.ZeroUtil.ClassNames.SET;
import static net.zerobuilder.compiler.generate.ZeroUtil.rawClassName;
import static net.zerobuilder.compiler.generate.ZeroUtil.upcase;
public final class DtoStep {
private static final Set LIST_HIERARCHY
= new HashSet<>(Arrays.asList(ClassNames.LIST, COLLECTION, ITERABLE));
public static final class CollectionInfo {
/**
* Initializer for a variable of type {@link AbstractParameter#type}.
* It evaluates to an empty List or Set.
*/
public final CodeBlock initializer;
/**
* Name of the convenience method to be generated, e.g. {@code "emptyFoo"}
*/
public final String name;
private CollectionInfo(CodeBlock initializer, String name) {
this.initializer = initializer;
this.name = name;
}
static Optional create(TypeName type, String name) {
Optional maybeClassName = rawClassName(type);
if (!maybeClassName.isPresent()) {
return Optional.empty();
}
ClassName className = maybeClassName.get();
if (LIST_HIERARCHY.contains(className)) {
return Optional.of(new CollectionInfo(
CodeBlock.of("$T.emptyList()", Collections.class),
emptyOptionName(name)));
}
if (SET.equals(className)) {
return Optional.of(new CollectionInfo(
CodeBlock.of("$T.emptySet()", Collections.class),
emptyOptionName(name)));
}
return Optional.empty();
}
private static String emptyOptionName(String name) {
return "empty" + upcase(name);
}
}
public static abstract class AbstractStep {
public final AbstractGoalDetails goalDetails;
public final BuildersContext context;
public final String thisType;
private final Optional extends AbstractStep> nextStep;
public final boolean isLast() {
return !nextStep.isPresent();
}
public static TypeName nextType(AbstractStep step) {
if (step.nextStep.isPresent()) {
return step.context.generatedType
.nestedClass(upcase(step.goalDetails.name() + "Builder"))
.nestedClass(step.nextStep.get().thisType);
}
return step.goalDetails.type();
}
AbstractStep(String thisType,
Optional extends AbstractStep> nextStep,
AbstractGoalDetails goalDetails,
BuildersContext context) {
this.thisType = thisType;
this.nextStep = nextStep;
this.goalDetails = goalDetails;
this.context = context;
}
abstract R accept(StepCases cases);
final AbstractParameter abstractParameter() {
return abstractParameter.apply(this);
}
}
interface StepCases {
R regularStep(AbstractRegularStep regular);
R beanStep(AbstractBeanStep bean);
}
static Function asFunction(final StepCases cases) {
return abstractStep -> abstractStep.accept(cases);
}
static StepCases stepCases(final Function super AbstractRegularStep, R> regularFunction,
final Function super AbstractBeanStep, R> beanFunction) {
return new StepCases() {
@Override
public R regularStep(AbstractRegularStep step) {
return regularFunction.apply(step);
}
@Override
public R beanStep(AbstractBeanStep step) {
return beanFunction.apply(step);
}
};
}
private static final Function abstractParameter
= asFunction(new StepCases() {
@Override
public AbstractParameter regularStep(AbstractRegularStep step) {
return step.regularParameter();
}
@Override
public AbstractParameter beanStep(AbstractBeanStep step) {
return step.beanParameter();
}
});
static Function always(final Function parameterFunction) {
return asFunction(new StepCases() {
@Override
public R regularStep(AbstractRegularStep step) {
return parameterFunction.apply(step);
}
@Override
public R beanStep(AbstractBeanStep step) {
return parameterFunction.apply(step);
}
});
}
private DtoStep() {
throw new UnsupportedOperationException("no instances");
}
}