public DaoReturnType parse()

in mapper-processor/src/main/java/com/datastax/oss/driver/internal/mapper/processor/dao/DefaultDaoReturnTypeParser.java [143:250]


  public DaoReturnType parse(
      @NonNull TypeMirror returnTypeMirror, @NonNull Map<Name, TypeElement> typeParameters) {

    // void or a primitive?
    DaoReturnType match = typeKindMatches.get(returnTypeMirror.getKind());
    if (match != null) {
      return match;
    }

    if (returnTypeMirror.getKind() == TypeKind.DECLARED) {

      // entity class? e.g. Product
      TypeElement entityElement;
      if ((entityElement = EntityUtils.asEntityElement(returnTypeMirror, typeParameters)) != null) {
        return new DaoReturnType(DefaultDaoReturnTypeKind.ENTITY, entityElement);
      }

      // simple class? e.g. Boolean
      DeclaredType declaredReturnType = (DeclaredType) returnTypeMirror;
      for (Map.Entry<Class<?>, DaoReturnType> entry : classMatches.entrySet()) {
        Class<?> simpleClass = entry.getKey();
        if (context.getClassUtils().isSame(declaredReturnType, simpleClass)) {
          return entry.getValue();
        }
      }

      // entity container? e.g. Optional<Product>
      if (declaredReturnType.getTypeArguments().size() == 1
          && (entityElement =
                  EntityUtils.typeArgumentAsEntityElement(returnTypeMirror, typeParameters))
              != null) {
        Element returnElement = declaredReturnType.asElement();
        for (Map.Entry<Class<?>, DaoReturnTypeKind> entry : entityContainerMatches.entrySet()) {
          Class<?> containerClass = entry.getKey();
          if (context.getClassUtils().isSame(returnElement, containerClass)) {
            return new DaoReturnType(entry.getValue(), entityElement);
          }
        }
      }

      if (context.getClassUtils().isFuture(declaredReturnType)) {
        TypeMirror typeArgumentMirror = declaredReturnType.getTypeArguments().get(0);

        // future of a simple class? e.g. CompletableFuture<Boolean>
        for (Map.Entry<Class<?>, DaoReturnType> entry : futureOfClassMatches.entrySet()) {
          Class<?> simpleClassArgument = entry.getKey();
          if (context.getClassUtils().isSame(typeArgumentMirror, simpleClassArgument)) {
            return entry.getValue();
          }
        }

        // Note that futures of entities (e.g. CompletionStage<Product>) are already covered by the
        // "entity container" check above

        // future of entity container? e.g. CompletionStage<Optional<Product>>
        if (typeArgumentMirror.getKind() == TypeKind.DECLARED) {
          DeclaredType declaredTypeArgument = (DeclaredType) typeArgumentMirror;
          if (declaredTypeArgument.getTypeArguments().size() == 1
              && (entityElement =
                      EntityUtils.typeArgumentAsEntityElement(typeArgumentMirror, typeParameters))
                  != null) {
            Element typeArgumentElement = declaredTypeArgument.asElement();
            for (Map.Entry<Class<?>, DaoReturnTypeKind> entry :
                futureOfEntityContainerMatches.entrySet()) {
              Class<?> containerClass = entry.getKey();
              if (context.getClassUtils().isSame(typeArgumentElement, containerClass)) {
                return new DaoReturnType(entry.getValue(), entityElement);
              }
            }
          }
        }
      }

      // Otherwise assume a custom type. A MappedResultProducer will be looked up from the
      // MapperContext at runtime.
      if (context.areCustomResultsEnabled()) {
        return new DaoReturnType(
            DefaultDaoReturnTypeKind.CUSTOM,
            findEntityInCustomType(declaredReturnType, typeParameters, new ArrayList<>()));
      }
    }

    if (returnTypeMirror.getKind() == TypeKind.TYPEVAR) {

      // entity class? e.g. Product
      TypeElement entityElement;
      if ((entityElement = EntityUtils.asEntityElement(returnTypeMirror, typeParameters)) != null) {
        return new DaoReturnType(DefaultDaoReturnTypeKind.ENTITY, entityElement);
      }

      // simple class? e.g. Boolean
      TypeVariable typeVariable = ((TypeVariable) returnTypeMirror);
      Name name = typeVariable.asElement().getSimpleName();
      TypeElement element = typeParameters.get(name);
      if (element != null) {
        for (Map.Entry<Class<?>, DaoReturnType> entry : classMatches.entrySet()) {
          Class<?> simpleClass = entry.getKey();
          if (context.getClassUtils().isSame(element, simpleClass)) {
            return entry.getValue();
          }
        }
      }

      // DAO parameterization by more complex types (futures, containers...) is not supported
    }

    return DaoReturnType.UNSUPPORTED;
  }