public Optional generate()

in mapper-processor/src/main/java/com/datastax/oss/driver/internal/mapper/processor/dao/DaoGetEntityMethodGenerator.java [72:201]


  public Optional<MethodSpec> generate() {

    // Validate the parameter: there must be exactly one, of type GettableByName or a ResultSet:
    if (methodElement.getParameters().size() != 1) {
      context
          .getMessager()
          .error(
              methodElement,
              "Wrong number of parameters: %s methods must have exactly one",
              GetEntity.class.getSimpleName());
      return Optional.empty();
    }
    VariableElement parameterElement = methodElement.getParameters().get(0);
    String parameterName = parameterElement.getSimpleName().toString();
    TypeMirror parameterType = parameterElement.asType();
    boolean parameterIsGettable = context.getClassUtils().implementsGettableByName(parameterType);
    boolean parameterIsResultSet = context.getClassUtils().isSame(parameterType, ResultSet.class);
    boolean parameterIsAsyncResultSet =
        context.getClassUtils().isSame(parameterType, AsyncResultSet.class);
    if (!parameterIsGettable && !parameterIsResultSet && !parameterIsAsyncResultSet) {
      context
          .getMessager()
          .error(
              methodElement,
              "Invalid parameter type: %s methods must take a %s, %s or %s",
              GetEntity.class.getSimpleName(),
              GettableByName.class.getSimpleName(),
              ResultSet.class.getSimpleName(),
              AsyncResultSet.class.getSimpleName());
      return Optional.empty();
    }

    // Validate the return type. Make sure it matches the parameter type
    Transformation transformation = null;
    TypeMirror returnType = methodElement.getReturnType();
    TypeElement entityElement = EntityUtils.asEntityElement(returnType, typeParameters);
    if (entityElement != null) {
      transformation = parameterIsGettable ? Transformation.NONE : Transformation.ONE;
    } else if (returnType.getKind() == TypeKind.DECLARED) {
      Element element = ((DeclaredType) returnType).asElement();
      if (context.getClassUtils().isSame(element, PagingIterable.class)) {
        if (!parameterIsResultSet) {
          context
              .getMessager()
              .error(
                  methodElement,
                  "Invalid return type: %s methods returning %s must have an argument of type %s",
                  GetEntity.class.getSimpleName(),
                  PagingIterable.class.getSimpleName(),
                  ResultSet.class.getSimpleName());
          return Optional.empty();
        }
        entityElement = EntityUtils.typeArgumentAsEntityElement(returnType, typeParameters);
        transformation = Transformation.MAP;
      } else if (context.getClassUtils().isSame(element, Stream.class)) {
        if (!parameterIsResultSet) {
          context
              .getMessager()
              .error(
                  methodElement,
                  "Invalid return type: %s methods returning %s must have an argument of type %s",
                  GetEntity.class.getSimpleName(),
                  Stream.class.getSimpleName(),
                  ResultSet.class.getSimpleName());
          return Optional.empty();
        }
        entityElement = EntityUtils.typeArgumentAsEntityElement(returnType, typeParameters);
        transformation = Transformation.STREAM;
      } else if (context.getClassUtils().isSame(element, MappedAsyncPagingIterable.class)) {
        if (!parameterIsAsyncResultSet) {
          context
              .getMessager()
              .error(
                  methodElement,
                  "Invalid return type: %s methods returning %s must have an argument of type %s",
                  GetEntity.class.getSimpleName(),
                  MappedAsyncPagingIterable.class.getSimpleName(),
                  AsyncResultSet.class.getSimpleName());
          return Optional.empty();
        }
        entityElement = EntityUtils.typeArgumentAsEntityElement(returnType, typeParameters);
        transformation = Transformation.MAP;
      }
    }
    if (entityElement == null) {
      context
          .getMessager()
          .error(
              methodElement,
              "Invalid return type: "
                  + "%s methods must return a %s-annotated class, or a %s, a %s or %s thereof",
              GetEntity.class.getSimpleName(),
              Entity.class.getSimpleName(),
              PagingIterable.class.getSimpleName(),
              Stream.class.getSimpleName(),
              MappedAsyncPagingIterable.class.getSimpleName());
      return Optional.empty();
    }

    // Generate the implementation:
    String helperFieldName = enclosingClass.addEntityHelperField(ClassName.get(entityElement));

    MethodSpec.Builder overridingMethodBuilder =
        GeneratedCodePatterns.override(methodElement, typeParameters);
    switch (transformation) {
      case NONE:
        overridingMethodBuilder.addStatement(
            "return $L.get($L, $L)", helperFieldName, parameterName, lenient);
        break;
      case ONE:
        overridingMethodBuilder
            .addStatement("$T row = $L.one()", Row.class, parameterName)
            .addStatement(
                "return (row == null) ? null : $L.get(row, $L)", helperFieldName, lenient);
        break;
      case MAP:
        overridingMethodBuilder.addStatement(
            "return $L.map(row -> $L.get(row, $L))", parameterName, helperFieldName, lenient);
        break;
      case STREAM:
        overridingMethodBuilder.addStatement(
            "return $T.stream($L.map(row -> $L.get(row, $L)).spliterator(), false)",
            StreamSupport.class,
            parameterName,
            helperFieldName,
            lenient);
        break;
    }
    return Optional.of(overridingMethodBuilder.build());
  }