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

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

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

import com.squareup.javapoet.TypeName;
import net.zerobuilder.compiler.generate.DtoBeanParameter.AbstractBeanParameter;
import net.zerobuilder.compiler.generate.DtoGoal.AbstractGoalDetails;
import net.zerobuilder.compiler.generate.DtoGoal.BeanGoalDetails;
import net.zerobuilder.compiler.generate.DtoGoal.RegularGoalDetails;
import net.zerobuilder.compiler.generate.DtoParameter.RegularParameter;

import java.util.List;
import java.util.function.Function;

public final class DtoGoalDescription {

  public interface GoalDescription {
     R accept(GoalDescriptionCases cases);
  }

  interface GoalDescriptionCases {
    R regularGoal(RegularGoalDescription goal);
    R beanGoal(BeanGoalDescription goal);
  }

  static  Function asFunction(final GoalDescriptionCases cases) {
    return goal -> goal.accept(cases);
  }

  /**
   * Describes of a goal that represents either a static method or an instance method, or a constructor.
   */
  public static final class RegularGoalDescription implements GoalDescription {
    final RegularGoalDetails details;
    final List thrownTypes;
    final List parameters;

    private RegularGoalDescription(RegularGoalDetails details,
                                   List thrownTypes,
                                   List parameters) {
      this.details = details;
      this.thrownTypes = thrownTypes;
      this.parameters = parameters;
    }

    /**
     * @param details     goal details
     * @param thrownTypes exceptions thrown by the goal method, if any
     * @param parameters  parameter names, possibly in a different order;
     *                    must contain each parameter name in {@link RegularGoalDetails#parameterNames}
     *                    exactly once
     * @return goal description
     * @throws IllegalArgumentException if {@code parameters} don't match the parameter names in {@code details}
     */
    public static RegularGoalDescription create(RegularGoalDetails details,
                                                List thrownTypes,
                                                List parameters) {
      checkParameterNames(details.parameterNames, parameters);
      validateProjectionInfo(details.goalOptions, parameters);
      return new RegularGoalDescription(details, thrownTypes, parameters);
    }

    private static void validateProjectionInfo(DtoGoal.GoalOptions options,
                                               List parameters) {
      if (!options.toBuilder) {
        return;
      }
      if (parameters.stream()
          .map(parameter -> parameter.projectionInfo)
          .allMatch(DtoProjectionInfo.isPresent)) {
        return;
      }
      throw new IllegalStateException("projection info required");
    }

    private static void checkParameterNames(List parameterNames,
                                            List parameters) {
      if (parameters.isEmpty()) {
        throw new IllegalArgumentException("need at least one parameter");
      }
      if (parameterNames.size() != parameters.size()) {
        throw new IllegalArgumentException("parameter names mismatch");
      }
      int[] positions = new int[parameterNames.size()];
      for (RegularParameter parameter : parameters) {
        int i = parameterNames.indexOf(parameter.name);
        if (positions[i]++ != 0) {
          throw new IllegalArgumentException("parameter names mismatch");
        }
      }
    }

    @Override
    public  R accept(GoalDescriptionCases cases) {
      return cases.regularGoal(this);
    }
  }

  /**
   * Describes the task of creating and / or updating a JavaBean.
   */
  public static final class BeanGoalDescription implements GoalDescription {
    final BeanGoalDetails details;
    final List parameters;

    private BeanGoalDescription(BeanGoalDetails details, List parameters) {
      this.details = details;
      this.parameters = parameters;
    }

    public static BeanGoalDescription create(BeanGoalDetails details, List parameters) {
      return new BeanGoalDescription(details, parameters);
    }
    @Override
    public  R accept(GoalDescriptionCases cases) {
      return cases.beanGoal(this);
    }
  }

  private static final Function abstractGoal =
      asFunction(new GoalDescriptionCases() {
        @Override
        public AbstractGoalDetails regularGoal(RegularGoalDescription goal) {
          return goal.details;
        }
        @Override
        public AbstractGoalDetails beanGoal(BeanGoalDescription goal) {
          return goal.details;
        }
      });

  static String goalName(GoalDescription goal) {
    return abstractGoal.apply(goal).name;
  }

  static TypeName goalType(GoalDescription goal) {
    return DtoGoal.goalType.apply(DtoGoalDescription.abstractGoal.apply(goal));
  }

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy