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

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

The newest version!
package net.zerobuilder.compiler.generate;

import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;

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

import static com.squareup.javapoet.ClassName.OBJECT;
import static net.zerobuilder.compiler.generate.ZeroUtil.distinctFrom;
import static net.zerobuilder.compiler.generate.ZeroUtil.downcase;
import static net.zerobuilder.compiler.generate.ZeroUtil.onlyTypeArgument;
import static net.zerobuilder.compiler.generate.ZeroUtil.parameterSpec;
import static net.zerobuilder.compiler.generate.ZeroUtil.simpleName;
import static net.zerobuilder.compiler.generate.ZeroUtil.upcase;

public final class DtoBeanParameter {

  interface BeanParameterCases {
    R accessorPair(AccessorPair pair);
    R loneGetter(LoneGetter getter);
  }

  private static  Function asFunction(BeanParameterCases cases) {
    return parameter -> parameter.accept(cases);
  }

  public static  Function beanParameterCases(
      Function accessorPairFunction,
      Function loneGetterFunction) {
    return asFunction(new BeanParameterCases() {
      @Override
      public R accessorPair(AccessorPair pair) {
        return accessorPairFunction.apply(pair);
      }
      @Override
      public R loneGetter(LoneGetter getter) {
        return loneGetterFunction.apply(getter);
      }
    });
  }

  private static final Function> getterThrownTypes =
      beanParameterCases(
          accessorPair -> accessorPair.getterThrownTypes,
          loneGetter -> loneGetter.getterThrownTypes);

  private static final Function> setterThrownTypes =
      beanParameterCases(
          accessorPair -> accessorPair.setterThrownTypes,
          loneGetter -> Collections.emptyList());


  public static abstract class AbstractBeanParameter {

    /**
     * the type that's returned by the getter,
     * or equivalently the type of the setter parameter
     */
    public final TypeName type;

    /**
     * true if null checks should be added
     */
    public final NullPolicy nullPolicy;


    /**
     * Name of the getter method (could start with {@code "is"})
     */
    public final String getter;

    public final List getterThrownTypes;

    private final String name;

    private AbstractBeanParameter(TypeName type, String getter, NullPolicy nullPolicy, List getterThrownTypes) {
      this.type = type;
      this.nullPolicy = nullPolicy;
      this.getter = getter;
      this.getterThrownTypes = getterThrownTypes;
      this.name = downcase(getter.substring(getter.startsWith("is") ? 2 : 3));
    }

    public final List getterThrownTypes() {
      return DtoBeanParameter.getterThrownTypes.apply(this);
    }

    public final List setterThrownTypes() {
      return DtoBeanParameter.setterThrownTypes.apply(this);
    }

    public final String name() {
      return name;
    }

    public abstract  R accept(BeanParameterCases cases);
  }

  public static final class AccessorPair extends AbstractBeanParameter {

    public final List setterThrownTypes;

    private final String setterName;

    private AccessorPair(TypeName type, String getter, NullPolicy nullPolicy,
                         List getterThrownTypes, List setterThrownTypes) {
      super(type, getter, nullPolicy, getterThrownTypes);
      this.setterThrownTypes = setterThrownTypes;
      this.setterName = "set" + upcase(name());
    }

    public String setterName() {
      return setterName;
    }

    @Override
    public  R accept(BeanParameterCases cases) {
      return cases.accessorPair(this);
    }
  }

  public static final class LoneGetter extends AbstractBeanParameter {

    /**
     * Example: If getter returns {@code List}, then this would be a variable of type
     * {@code String}
     */
    private final ParameterSpec iterationVar;

    public TypeName iterationType() {
      return iterationVar.type;
    }

    /**
     * A helper method to avoid conflicting variable name.
     *
     * @param avoid a variable name
     * @return a variable that's different from {@code avoid}, preferably {@link #iterationVar}
     */
    public ParameterSpec iterationVar(ParameterSpec avoid) {
      if (!iterationVar.name.equals(avoid.name)) {
        return iterationVar;
      }
      return parameterSpec(iterationVar.type, distinctFrom(iterationVar.name, avoid.name));
    }

    private LoneGetter(TypeName type, String getter, NullPolicy nullPolicy, ParameterSpec iterationVar,
                       List getterThrownTypes) {
      super(type, getter, nullPolicy, getterThrownTypes);
      this.iterationVar = iterationVar;
    }

    @Override
    public  R accept(BeanParameterCases cases) {
      return cases.loneGetter(this);
    }
  }

  /**
   * Creates a parameter object that describes a standard accessor pair.
   *
   * @param type              the type returned by the getter
   * @param getter            getter name
   * @param nullPolicy        null policy
   * @param getterThrownTypes thrown types
   * @param setterThrownTypes thrown types
   * @return accessor pair
   */
  public static AbstractBeanParameter accessorPair(TypeName type, String getter, NullPolicy nullPolicy,
                                                   List getterThrownTypes, List setterThrownTypes) {
    return new AccessorPair(type, getter, nullPolicy,
        getterThrownTypes, setterThrownTypes);
  }

  /**
   * Creates a parameter object that describes a lone getter accessor.
   *
   * @param type              should be a subclass of {@link java.util.Collection}
   * @param getter            getter name
   * @param nullPolicy        null policy
   * @param getterThrownTypes thrown types
   * @return lone getter
   * @throws IllegalArgumentException if {@code type} has more than one type parameter
   */
  public static AbstractBeanParameter loneGetter(TypeName type, String getter, NullPolicy nullPolicy,
                                                 List getterThrownTypes) {
    TypeName collectionType = onlyTypeArgument(type).orElse(OBJECT);
    String name = downcase(simpleName(collectionType));
    ParameterSpec iterationVar = parameterSpec(collectionType, name);
    return new LoneGetter(type, getter, nullPolicy, iterationVar, getterThrownTypes);
  }

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




© 2015 - 2025 Weber Informatics LLC | Privacy Policy