net.zerobuilder.compiler.generate.GoalContextFactory Maven / Gradle / Ivy
package net.zerobuilder.compiler.generate;
import com.squareup.javapoet.TypeName;
import net.zerobuilder.compiler.generate.DtoBeanGoal.BeanGoalContext;
import net.zerobuilder.compiler.generate.DtoBeanGoalDescription.BeanGoalDescription;
import net.zerobuilder.compiler.generate.DtoBeanParameter.AbstractBeanParameter;
import net.zerobuilder.compiler.generate.DtoBeanParameter.AccessorPair;
import net.zerobuilder.compiler.generate.DtoBeanParameter.BeanParameterCases;
import net.zerobuilder.compiler.generate.DtoBeanParameter.LoneGetter;
import net.zerobuilder.compiler.generate.DtoBeanStep.AbstractBeanStep;
import net.zerobuilder.compiler.generate.DtoBeanStep.AccessorPairStep;
import net.zerobuilder.compiler.generate.DtoBeanStep.LoneGetterStep;
import net.zerobuilder.compiler.generate.DtoConstructorGoal.SimpleConstructorGoalContext;
import net.zerobuilder.compiler.generate.DtoContext.BuildersContext;
import net.zerobuilder.compiler.generate.DtoDescriptionInput.DescriptionInput;
import net.zerobuilder.compiler.generate.DtoGeneratorInput.AbstractGoalInput;
import net.zerobuilder.compiler.generate.DtoGeneratorInput.GoalInput;
import net.zerobuilder.compiler.generate.DtoGeneratorInput.ProjectedGoalInput;
import net.zerobuilder.compiler.generate.DtoGoalDetails.AbstractGoalDetails;
import net.zerobuilder.compiler.generate.DtoGoalDetails.ConstructorGoalDetails;
import net.zerobuilder.compiler.generate.DtoGoalDetails.InstanceMethodGoalDetails;
import net.zerobuilder.compiler.generate.DtoGoalDetails.ProjectableDetailsCases;
import net.zerobuilder.compiler.generate.DtoGoalDetails.RegularGoalDetailsCases;
import net.zerobuilder.compiler.generate.DtoGoalDetails.StaticMethodGoalDetails;
import net.zerobuilder.compiler.generate.DtoMethodGoal.InstanceMethodGoalContext;
import net.zerobuilder.compiler.generate.DtoMethodGoal.SimpleStaticMethodGoalContext;
import net.zerobuilder.compiler.generate.DtoParameter.AbstractParameter;
import net.zerobuilder.compiler.generate.DtoProjectedGoal.ProjectedGoal;
import net.zerobuilder.compiler.generate.DtoProjectedRegularGoalContext.ProjectedConstructorGoalContext;
import net.zerobuilder.compiler.generate.DtoProjectedRegularGoalContext.ProjectedMethodGoalContext;
import net.zerobuilder.compiler.generate.DtoRegularGoal.SimpleRegularGoalContext;
import net.zerobuilder.compiler.generate.DtoRegularGoalDescription.ProjectedRegularGoalDescription;
import net.zerobuilder.compiler.generate.DtoRegularGoalDescription.SimpleRegularGoalDescription;
import net.zerobuilder.compiler.generate.DtoRegularParameter.ProjectedParameter;
import net.zerobuilder.compiler.generate.DtoRegularParameter.SimpleParameter;
import net.zerobuilder.compiler.generate.DtoRegularStep.ProjectedRegularStep;
import net.zerobuilder.compiler.generate.DtoRegularStep.SimpleRegularStep;
import net.zerobuilder.compiler.generate.DtoSimpleGoal.SimpleGoal;
import net.zerobuilder.compiler.generate.DtoStep.AbstractStep;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import static java.util.Collections.emptyList;
import static net.zerobuilder.compiler.generate.DtoDescriptionInput.descriptionInputCases;
import static net.zerobuilder.compiler.generate.DtoParameter.parameterName;
import static net.zerobuilder.compiler.generate.DtoProjectedDescription.projectedDescriptionCases;
import static net.zerobuilder.compiler.generate.DtoSimpleDescription.simpleDescriptionCases;
import static net.zerobuilder.compiler.generate.ZeroUtil.reverse;
import static net.zerobuilder.compiler.generate.ZeroUtil.upcase;
final class GoalContextFactory {
private static BeanGoalContext prepareBean(
BuildersContext context,
BeanGoalDescription goal) {
List steps = steps(
goal.details,
goal.thrownTypes,
context,
goal.parameters,
beanFactory);
return new BeanGoalContext(context, goal.details, steps, goal.thrownTypes);
}
private static SimpleGoal prepareRegular(
BuildersContext context,
SimpleRegularGoalDescription simple) {
List steps = steps(
simple.details,
simple.thrownTypes,
context,
simple.parameters,
simpleRegularFactory);
return simple.details.accept(new RegularGoalDetailsCases() {
@Override
public SimpleRegularGoalContext method(InstanceMethodGoalDetails details) {
return new InstanceMethodGoalContext(context, details, steps, simple.thrownTypes);
}
@Override
public SimpleRegularGoalContext staticMethod(StaticMethodGoalDetails details) {
return new SimpleStaticMethodGoalContext(context, details, steps, simple.thrownTypes);
}
@Override
public SimpleRegularGoalContext constructor(ConstructorGoalDetails details) {
return new SimpleConstructorGoalContext(context, details, steps, simple.thrownTypes);
}
});
}
private static ProjectedGoal prepareProjectedRegular(
BuildersContext context,
ProjectedRegularGoalDescription description) {
List steps = steps(
description.details,
description.thrownTypes,
context,
description.parameters,
projectedRegularFactory);
return description.details.accept(new ProjectableDetailsCases() {
@Override
public ProjectedGoal constructor(ConstructorGoalDetails constructor) {
return new ProjectedConstructorGoalContext(context, constructor, steps, description.thrownTypes);
}
@Override
public ProjectedGoal method(StaticMethodGoalDetails method) {
return new ProjectedMethodGoalContext(context, method, steps, description.thrownTypes);
}
});
}
private static List steps(
AbstractGoalDetails details,
List thrownTypes,
BuildersContext context,
List parameters,
Function
> factoryFactory) {
Optional nextStep = Optional.empty();
List builder = new ArrayList<>(parameters.size());
for (P parameter : reverse(parameters)) {
String thisType = upcase(parameterName.apply(parameter));
StepFactory factory = factoryFactory.apply(parameter);
S step = factory.create(
thisType,
nextStep,
details,
context,
thrownTypes);
builder.add(step);
thrownTypes = emptyList();
nextStep = Optional.of(step);
}
return reverse(builder);
}
private static abstract class StepFactory {
abstract S create(String thisType,
Optional nextType,
AbstractGoalDetails goalDetails,
BuildersContext context,
List thrownTypes);
}
private static final Function> beanFactory =
beanParameter -> new StepFactory() {
@Override
AbstractBeanStep create(String thisType,
Optional nextType,
AbstractGoalDetails goalDetails,
BuildersContext context,
List declaredExceptions) {
return beanParameter.accept(new BeanParameterCases() {
@Override
public AbstractBeanStep accessorPair(AccessorPair pair) {
return AccessorPairStep.create(
thisType,
nextType,
goalDetails,
context,
pair);
}
@Override
public AbstractBeanStep loneGetter(LoneGetter loneGetter) {
return LoneGetterStep.create(
thisType,
nextType,
goalDetails,
context,
loneGetter);
}
});
}
};
private static final Function> simpleRegularFactory =
regularParameter -> new StepFactory() {
@Override
SimpleRegularStep create(String thisType, Optional nextType, AbstractGoalDetails goalDetails, BuildersContext context, List thrownTypes) {
return SimpleRegularStep.create(
thisType,
nextType,
goalDetails,
context,
regularParameter);
}
};
private static final Function> projectedRegularFactory =
regularParameter -> new StepFactory() {
@Override
ProjectedRegularStep create(String thisType, Optional nextType, AbstractGoalDetails goalDetails, BuildersContext context, List thrownTypes) {
return ProjectedRegularStep.create(
thisType,
nextType,
goalDetails,
context,
regularParameter,
thrownTypes);
}
};
static Function prepare(BuildersContext context) {
return descriptionInputCases(
(module, description) -> new GoalInput(
module,
simpleDescriptionCases(
regular -> GoalContextFactory.prepareRegular(
context, regular),
bean -> GoalContextFactory.prepareBean(
context, bean)).apply(description)),
(module, description) -> new ProjectedGoalInput(
module,
projectedDescriptionCases(
regular -> prepareProjectedRegular(
context, regular),
bean -> GoalContextFactory.prepareBean(
context, bean)).apply(description)));
}
}