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

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

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

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;
import net.zerobuilder.NullPolicy;
import net.zerobuilder.compiler.generate.DtoParameter.AbstractParameter;
import net.zerobuilder.compiler.generate.DtoProjectedParameter.AbstractProjectedParameter;

import java.util.List;
import java.util.function.Supplier;

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.memoize;
import static net.zerobuilder.compiler.generate.ZeroUtil.onlyTypeArgument;
import static net.zerobuilder.compiler.generate.ZeroUtil.parameterSpec;
import static net.zerobuilder.compiler.generate.ZeroUtil.rawClassName;
import static net.zerobuilder.compiler.generate.ZeroUtil.upcase;

public final class DtoBeanParameter {

  public static abstract class AbstractBeanParameter extends AbstractParameter implements AbstractProjectedParameter {

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

    public final List getterThrownTypes;

    private final Supplier name;

    private AbstractBeanParameter(TypeName type, String getter, NullPolicy nullPolicy, List getterThrownTypes) {
      super(type, nullPolicy);
      this.getter = getter;
      this.getterThrownTypes = getterThrownTypes;
      this.name = memoizeName(getter);
    }

    private static Supplier memoizeName(String getter) {
      return memoize(() ->
          downcase(getter.substring(getter.startsWith("is") ? 2 : 3)));
    }

    @Override
    public final String name() {
      return name.get();
    }

    public abstract  R accept(BeanParameterCases cases);
    @Override
    public final  R acceptParameter(DtoParameter.ParameterCases cases) {
      return cases.beanParameter(this);
    }

    @Override
    public final  R acceptProjected(DtoProjectedParameter.ProjectedParameterCases cases) {
      return cases.projectedBean(this);
    }
  }

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

  public static final class AccessorPair extends AbstractBeanParameter {

    public final List setterThrownTypes;

    private final Supplier setterName;

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

    private static Supplier memoizeSetterName(String name) {
      return memoize(() -> "set" + upcase(name));
    }

    public String setterName() {
      return setterName.get();
    }

    @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 = rawClassName(collectionType)
        .map(ClassName::simpleName)
        .map(ZeroUtil::downcase)
        .orElseThrow(IllegalStateException::new);
    ParameterSpec iterationVar = parameterSpec(collectionType, name);
    return new LoneGetter(type, getter, nullPolicy, iterationVar, getterThrownTypes);
  }

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy