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

net.zerobuilder.compiler.analyse.ProjectionValidator Maven / Gradle / Ivy

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

import com.squareup.javapoet.TypeName;
import net.zerobuilder.Getter;
import net.zerobuilder.Step;
import net.zerobuilder.compiler.generate.DtoBeanParameter;
import net.zerobuilder.compiler.generate.DtoBeanParameter.AbstractBeanParameter;
import net.zerobuilder.compiler.generate.DtoProjectionInfo.ProjectionInfo;
import net.zerobuilder.compiler.generate.DtoRegularParameter;
import net.zerobuilder.compiler.generate.DtoRegularParameter.ProjectedParameter;
import net.zerobuilder.compiler.generate.DtoRegularParameter.SimpleParameter;

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

import static java.util.Collections.nCopies;
import static javax.tools.Diagnostic.Kind.ERROR;
import static net.zerobuilder.compiler.Messages.ErrorMessages.STEP_DUPLICATE;
import static net.zerobuilder.compiler.Messages.ErrorMessages.STEP_OUT_OF_BOUNDS;
import static net.zerobuilder.compiler.analyse.Utilities.thrownTypes;

final class ProjectionValidator {

  /**
   * Modifies the parameter order, depending on {@link Step} annotations.
   * If none of the parameters has a {@link Step} annotation, the
   * order of the input parameters is not changed.
   *
   * @param parameters parameters in original order
   * @param         parameter type
   * @return parameters in a potentially different order
   * @throws ValidationException if the input is inconsistent
   */
  static  List shuffledParameters(List parameters)
      throws ValidationException {
    List builder = new ArrayList<>(nCopies(parameters.size(), (E) null));
    List noAnnotation = new ArrayList<>();
    for (E parameter : parameters) {
      int value = parameter.annotation;
      if (value >= 0) {
        parameter
            .checkState(value < parameters.size(), STEP_OUT_OF_BOUNDS)
            .checkState(builder.get(value) == null, STEP_DUPLICATE);
        builder.set(value, parameter);
      } else {
        noAnnotation.add(parameter);
      }
    }
    int pos = 0;
    for (E parameter : noAnnotation) {
      while (builder.get(pos) != null) {
        pos++;
      }
      builder.set(pos++, parameter);
    }
    return builder;
  }

  static abstract class TmpValidParameter {

    final Element element;
    // step position
    final int annotation;

    private TmpValidParameter(Element element, int annotation) {
      this.element = element;
      this.annotation = annotation;
    }

    TmpValidParameter checkState(boolean condition, String message) {
      if (!condition) {
        throw new ValidationException(ERROR,
            message, element);
      }
      return this;
    }
  }

  static final class TmpSimpleParameter extends TmpValidParameter {
    final SimpleParameter parameter;

    private TmpSimpleParameter(Element element, int annotation, SimpleParameter parameter) {
      super(element, annotation);
      this.parameter = parameter;
    }

    static TmpSimpleParameter create(VariableElement parameter) {
      int value = parameter.getAnnotation(Step.class) == null ?
          -1 : parameter.getAnnotation(Step.class).value();
      String name = parameter.getSimpleName().toString();
      TypeName type = TypeName.get(parameter.asType());
      DtoRegularParameter.SimpleParameter regularParameter =
          DtoRegularParameter.create(name, type);
      return new TmpSimpleParameter(parameter, value, regularParameter);
    }
  }

  static final class TmpProjectedParameter extends TmpValidParameter {
    private final ProjectedParameter parameter;

    private TmpProjectedParameter(Element element, int annotation, ProjectedParameter parameter) {
      super(element, annotation);
      this.parameter = parameter;
    }

    static final Function toValidParameter =
        parameter -> parameter.parameter;

    static TmpProjectedParameter create(VariableElement parameter, ProjectionInfo projectionInfo) {
      int value = parameter.getAnnotation(Step.class) == null ?
          -1 : parameter.getAnnotation(Step.class).value();
      String name = parameter.getSimpleName().toString();
      TypeName type = TypeName.get(parameter.asType());
      ProjectedParameter regularParameter =
          DtoRegularParameter.create(name, type, projectionInfo);
      return new TmpProjectedParameter(parameter, value, regularParameter);
    }
  }

  static final class TmpAccessorPair extends TmpValidParameter {
    final AbstractBeanParameter parameter;

    private TmpAccessorPair(Element element, int annotation, AbstractBeanParameter parameter) {
      super(element, annotation);
      this.parameter = parameter;
    }

    static final Function toValidParameter = parameter -> parameter.parameter;

    static TmpAccessorPair accessorPair(ExecutableElement getter, ExecutableElement setter) {
      int value = getter.getAnnotation(Getter.class) == null ?
          -1 : getter.getAnnotation(Getter.class).value();
      TypeName type = TypeName.get(getter.getReturnType());
      AbstractBeanParameter accessorPair = DtoBeanParameter.accessorPair(type, getter.getSimpleName().toString(),
          thrownTypes(getter), thrownTypes(setter));
      return new TmpAccessorPair(getter, value, accessorPair);
    }

    static TmpAccessorPair createLoneGetter(ExecutableElement getter, AbstractBeanParameter loneGetter) {
      int value = getter.getAnnotation(Getter.class) == null ?
          -1 : getter.getAnnotation(Getter.class).value();
      return new TmpAccessorPair(getter, value, loneGetter);
    }
  }

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy