All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.zerobuilder.compiler.generate.Generator Maven / Gradle / Ivy

There is a newer version: 1.603
Show newest version
package net.zerobuilder.compiler.generate;

import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
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.GeneratorInput;
import net.zerobuilder.compiler.generate.DtoGeneratorOutput.BuilderMethod;
import net.zerobuilder.compiler.generate.DtoGeneratorOutput.GeneratorOutput;
import net.zerobuilder.compiler.generate.DtoInputOutput.AbstractInputOutput;
import net.zerobuilder.compiler.generate.DtoInputOutput.InputOutput;
import net.zerobuilder.compiler.generate.DtoInputOutput.ProjectedInputOutput;
import net.zerobuilder.compiler.generate.DtoModule.ContractModule;
import net.zerobuilder.compiler.generate.DtoModule.ModuleCases;
import net.zerobuilder.compiler.generate.DtoModule.SimpleModule;
import net.zerobuilder.compiler.generate.DtoModuleOutput.AbstractModuleOutput;
import net.zerobuilder.compiler.generate.DtoProjectedModule.ProjectedContractModule;
import net.zerobuilder.compiler.generate.DtoProjectedModule.ProjectedModuleCases;
import net.zerobuilder.compiler.generate.DtoProjectedModule.ProjectedSimpleModule;

import javax.lang.model.element.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collector;

import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static javax.lang.model.element.Modifier.PRIVATE;
import static net.zerobuilder.compiler.generate.DtoContext.BuilderLifecycle.NEW_INSTANCE;
import static net.zerobuilder.compiler.generate.DtoGeneratorInput.goalInputCases;
import static net.zerobuilder.compiler.generate.DtoModuleOutput.moduleOutputCases;
import static net.zerobuilder.compiler.generate.GoalContextFactory.prepare;
import static net.zerobuilder.compiler.generate.ZeroUtil.flatList;
import static net.zerobuilder.compiler.generate.ZeroUtil.listCollector;
import static net.zerobuilder.compiler.generate.ZeroUtil.transform;

public final class Generator {

  /**
   * Entry point for code generation.
   *
   * @param generatorInput Goal descriptions
   * @return a GeneratorOutput
   */
  public static GeneratorOutput generate(GeneratorInput generatorInput) {
    List goals = generatorInput.goals;
    BuildersContext context = generatorInput.context;
    return goals.stream()
        .map(prepare(context))
        .map(process)
        .collect(collectOutput(context));
  }

  private static Collector, GeneratorOutput> collectOutput(BuildersContext context) {
    return listCollector(tmpOutputs ->
        GeneratorOutput.create(
            methods(tmpOutputs),
            types(tmpOutputs),
            fields(context, tmpOutputs),
            context));
  }

  private static List methods(List inputOutputs) {
    return transform(inputOutputs, tmp -> tmp.output.method);
  }

  private static List types(List inputOutputs) {
    return inputOutputs.stream()
        .map(tmp -> nestedTypes.apply(tmp.output))
        .collect(flatList());
  }

  private static List fields(BuildersContext context, List inputOutputs) {
    if (context.lifecycle == NEW_INSTANCE) {
      return emptyList();
    }
    List fields = new ArrayList<>(inputOutputs.size() + 1);
    fields.add(context.cache.get());
    inputOutputs.forEach(tmp ->
        fields.add(tmp.cacheField()));
    return fields;
  }

  private static final Function process =
      goalInputCases(
          simpleInput -> new InputOutput(simpleInput.module, simpleInput.goal,
              simpleInput.module.accept(new ModuleCases() {
                @Override
                public AbstractModuleOutput simple(SimpleModule module, Void o) {
                  return module.process(simpleInput.goal);
                }
                @Override
                public AbstractModuleOutput contract(ContractModule module, Void o) {
                  return module.process(simpleInput.goal);
                }
              }, null)),
          projectedInput -> new ProjectedInputOutput(projectedInput.module, projectedInput.goal,
              projectedInput.module.accept(new ProjectedModuleCases() {
                @Override
                public AbstractModuleOutput simple(ProjectedSimpleModule module, Void aVoid) {
                  return module.process(projectedInput.goal);
                }
                @Override
                public AbstractModuleOutput contract(ProjectedContractModule module, Void aVoid) {
                  return module.process(projectedInput.goal);
                }
              }, null)));

  private static final Function> nestedTypes =
      moduleOutputCases(
          simple -> singletonList(simple.impl),
          contract -> asList(contract.impl, contract.contract));

  private Generator() {
    throw new UnsupportedOperationException("no instances");
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy