private static MethodDefinition createSettingsBeanMethod()

in spring-cloud-generator/src/main/java/com/google/cloud/generator/spring/composer/SpringAutoConfigClassComposer.java [447:848]


  private static MethodDefinition createSettingsBeanMethod(
      Service service,
      Transport transport,
      String transportChannelProviderName,
      Map<String, TypeNode> types,
      Expr thisExpr,
      String serviceSettingsMethodName) {

    // Generates code for argument variables:
    VariableExpr credentialsProviderVariableExpr =
        VariableExpr.withVariable(
            Variable.builder()
                .setName("credentialsProvider")
                .setType(STATIC_TYPES.get("CredentialsProvider"))
                .build());
    VariableExpr transportChannelProviderVariableExpr =
        VariableExpr.withVariable(
            Variable.builder()
                .setName("defaultTransportChannelProvider")
                .setType(STATIC_TYPES.get("TransportChannelProvider"))
                .build());
    MethodInvocationExpr defaultEnpointMethodInvocationExpr =
            MethodInvocationExpr.builder()
                    .setStaticReferenceType(types.get("ServiceSettings"))
                    .setMethodName("getDefaultEndpoint")
                    .setReturnType(TypeNode.STRING)
                    .build();

    List<Statement> bodyStatements = new ArrayList<>();

    Variable settingBuilderVariable =
        Variable.builder()
            .setName("clientSettingsBuilder")
            .setType(types.get("ServiceSettingsBuilder"))
            .build();

    VariableExpr settingsVarExpr =
        VariableExpr.withVariable(settingBuilderVariable).toBuilder().setIsDecl(true).build();

    Expr newBuilderExpr =
        MethodInvocationExpr.builder()
            .setStaticReferenceType(types.get("ServiceSettings"))
            .setMethodName("newBuilder")
            .setReturnType(types.get("ServiceSettingsBuilder"))
            .build();

    Variable clientPropertiesVar =
        Variable.builder()
            .setName("clientProperties")
            .setType(types.get(Utils.getServicePropertiesClassName(service)))
            .build();
    VariableExpr thisClientPropertiesVarExpr =
        VariableExpr.withVariable(clientPropertiesVar)
            .toBuilder()
            .setExprReferenceExpr(thisExpr)
            .build();

    if (ComposerUtils.shouldSupportRestOptionWithGrpcDefault(transport, service)) {
      // For GRPC+REST libraries, generates code to choose builder according to configuration property
      MethodInvocationExpr getUseRest =
          MethodInvocationExpr.builder()
              .setMethodName("getUseRest")
              .setReturnType(TypeNode.BOOLEAN)
              .setExprReferenceExpr(thisClientPropertiesVarExpr)
              .build();

      // If useRest property is true, generates code to use HTTP/JSON builder:
      // <Service>Settings.newHttpJsonBuilder()
      Expr newHttpJsonBuilderExpr =
          MethodInvocationExpr.builder()
              .setStaticReferenceType(types.get("ServiceSettings"))
              .setMethodName("newHttpJsonBuilder")
              .setReturnType(types.get("ServiceSettingsBuilder"))
              .build();

      AssignmentExpr newHttpJsonBuilderAssignmentExpr =
          AssignmentExpr.builder()
              .setVariableExpr(VariableExpr.withVariable(settingBuilderVariable))
              .setValueExpr(newHttpJsonBuilderExpr)
              .build();

      AssignmentExpr newBuilderAssignmentExpr =
          AssignmentExpr.builder()
              .setVariableExpr(VariableExpr.withVariable(settingBuilderVariable))
              .setValueExpr(newBuilderExpr)
              .build();

      ExprStatement newBuilderStatement = ExprStatement.withExpr(newBuilderAssignmentExpr);
      ExprStatement newHttpJsonBuilderStatement =
          ExprStatement.withExpr(newHttpJsonBuilderAssignmentExpr);

      IfStatement setClientSettingsBuilderStatement =
          createIfStatement(
              getUseRest,
              Arrays.asList(
                  newHttpJsonBuilderStatement,
                  LoggerUtils.createLoggerStatement(
                      ValueExpr.withValue(
                          StringObjectValue.withValue("Using REST (HTTP/JSON) transport.")),
                      types)),
              Arrays.asList(newBuilderStatement));

      bodyStatements.add(ExprStatement.withExpr(settingsVarExpr));
      bodyStatements.add(setClientSettingsBuilderStatement);

    } else {
      // For GRPC-only or REST-only libraries, generates code to use default builder:
      // <Service>Settings.newBuilder()
      AssignmentExpr clientSettingsBuilderAssignmentExpr =
          AssignmentExpr.builder()
              .setVariableExpr(settingsVarExpr)
              .setValueExpr(newBuilderExpr)
              .build();

      bodyStatements.add(ExprStatement.withExpr(clientSettingsBuilderAssignmentExpr));
    }

    VariableExpr thisCredentialsProvider =
        VariableExpr.withVariable(
                Variable.builder()
                    .setName("credentialsProvider")
                    .setType(STATIC_TYPES.get("CredentialsProvider"))
                    .build())
            .toBuilder()
            .setExprReferenceExpr(thisExpr)
            .build();

    Expr settingsBuilderExpr =
        MethodInvocationExpr.builder()
            .setExprReferenceExpr(VariableExpr.withVariable(settingBuilderVariable))
            .setMethodName("setCredentialsProvider")
            .setArguments(thisCredentialsProvider)
            .build();
    settingsBuilderExpr =
        MethodInvocationExpr.builder()
            .setExprReferenceExpr(settingsBuilderExpr)
            .setMethodName("setTransportChannelProvider")
            .setArguments(transportChannelProviderVariableExpr)
            .build();
    settingsBuilderExpr =
            MethodInvocationExpr.builder()
                    .setExprReferenceExpr(settingsBuilderExpr)
                    .setMethodName("setEndpoint")
                    .setArguments(defaultEnpointMethodInvocationExpr)
                    .build();
    MethodInvocationExpr userAgentHeaderProviderInvocation =
        MethodInvocationExpr.builder()
            .setExprReferenceExpr(thisExpr)
            .setMethodName("userAgentHeaderProvider")
            .setReturnType(STATIC_TYPES.get("HeaderProvider"))
            .build();
    settingsBuilderExpr =
        MethodInvocationExpr.builder()
            .setExprReferenceExpr(settingsBuilderExpr)
            .setMethodName("setHeaderProvider")
            .setArguments(userAgentHeaderProviderInvocation)
            .setReturnType(settingBuilderVariable.type())
            .build();

    bodyStatements.add(ExprStatement.withExpr(settingsBuilderExpr));

    // Set quota project ID if specified via configuration property
    MethodInvocationExpr getQuotaProjectId =
        MethodInvocationExpr.builder()
            .setMethodName("getQuotaProjectId")
            .setReturnType(TypeNode.STRING)
            .setExprReferenceExpr(thisClientPropertiesVarExpr)
            .build();
    RelationalOperationExpr projectIdIsNull =
        RelationalOperationExpr.notEqualToWithExprs(getQuotaProjectId, ValueExpr.createNullExpr());

    MethodInvocationExpr setQuotaProjectId =
        MethodInvocationExpr.builder()
            .setExprReferenceExpr(VariableExpr.withVariable(settingBuilderVariable))
            .setMethodName("setQuotaProjectId")
            .setArguments(getQuotaProjectId)
            .build();

    Statement projectIdLoggerStatement =
        LoggerUtils.createLoggerStatement(
            LoggerUtils.concatManyWithExprs(
                ValueExpr.withValue(StringObjectValue.withValue("Quota project id set to ")),
                getQuotaProjectId,
                ValueExpr.withValue(
                    StringObjectValue.withValue(", this overrides project id from credentials."))),
            types);

    IfStatement setQuotaProjectIdStatement =
        createIfStatement(
            projectIdIsNull,
            Arrays.asList(ExprStatement.withExpr(setQuotaProjectId), projectIdLoggerStatement),
            null);

    bodyStatements.add(setQuotaProjectIdStatement);

    // Set executor thread count if specified via configuration property
    MethodInvocationExpr getExecutorThreadCount =
        MethodInvocationExpr.builder()
            .setMethodName("getExecutorThreadCount")
            .setReturnType(TypeNode.INT_OBJECT)
            .setExprReferenceExpr(thisClientPropertiesVarExpr)
            .build();
    RelationalOperationExpr executorThreadCountIsNull =
        RelationalOperationExpr.notEqualToWithExprs(
            getExecutorThreadCount, ValueExpr.createNullExpr());

    VariableExpr executorProviderVarExpr =
        VariableExpr.withVariable(
            Variable.builder()
                .setType(STATIC_TYPES.get("ExecutorProvider"))
                .setName("executorProvider")
                .build());

    MethodInvocationExpr chainedMethodToSetExecutorProvider =
        MethodInvocationExpr.builder()
            .setStaticReferenceType(types.get("ServiceSettings"))
            .setMethodName("defaultExecutorProviderBuilder")
            .build();
    chainedMethodToSetExecutorProvider =
        MethodInvocationExpr.builder()
            .setExprReferenceExpr(chainedMethodToSetExecutorProvider)
            .setMethodName("setExecutorThreadCount")
            .setArguments(getExecutorThreadCount)
            .build();
    chainedMethodToSetExecutorProvider =
        MethodInvocationExpr.builder()
            .setExprReferenceExpr(chainedMethodToSetExecutorProvider)
            .setMethodName("build")
            .setReturnType(STATIC_TYPES.get("ExecutorProvider"))
            .build();
    AssignmentExpr executorProviderAssignExpr =
        AssignmentExpr.builder()
            .setVariableExpr(executorProviderVarExpr.toBuilder().setIsDecl(true).build())
            .setValueExpr(chainedMethodToSetExecutorProvider)
            .build();
    MethodInvocationExpr setBackgroundExecutorProvider =
        MethodInvocationExpr.builder()
            .setExprReferenceExpr(VariableExpr.withVariable(settingBuilderVariable))
            .setMethodName("setBackgroundExecutorProvider")
            .setArguments(executorProviderVarExpr)
            .build();

    Statement backgroundExecutorLoggerStatement =
        LoggerUtils.createLoggerStatement(
            ArithmeticOperationExpr.concatWithExprs(
                ValueExpr.withValue(
                    StringObjectValue.withValue("Background executor thread count is ")),
                getExecutorThreadCount),
            types);
    IfStatement setBackgroundExecutorProviderStatement =
        createIfStatement(
            executorThreadCountIsNull,
            Arrays.asList(
                ExprStatement.withExpr(executorProviderAssignExpr),
                ExprStatement.withExpr(setBackgroundExecutorProvider),
                backgroundExecutorLoggerStatement),
            null);

    bodyStatements.add(setBackgroundExecutorProviderStatement);

    // If service-level properties configured, update retry settings for each method
    Variable serviceRetryPropertiesVar =
        Variable.builder().setName("serviceRetry").setType(types.get("Retry")).build();

    VariableExpr serviceRetryPropertiesVarExpr =
        VariableExpr.builder().setVariable(serviceRetryPropertiesVar).setIsDecl(true).build();

    // Service-level retry configuration: clientProperties.getRetry()
    MethodInvocationExpr serviceRetryPropertiesExpr =
        MethodInvocationExpr.builder()
            .setExprReferenceExpr(VariableExpr.withVariable(clientPropertiesVar))
            .setMethodName("getRetry")
            .setReturnType(types.get("Retry"))
            .build();

    AssignmentExpr serviceRetrySettingsExpr =
        AssignmentExpr.builder()
            .setVariableExpr(serviceRetryPropertiesVarExpr)
            .setValueExpr(serviceRetryPropertiesExpr)
            .build();

    bodyStatements.add(ExprStatement.withExpr(serviceRetrySettingsExpr));

    RelationalOperationExpr serviceRetryPropertiesNotNull =
        RelationalOperationExpr.notEqualToWithExprs(
            VariableExpr.withVariable(serviceRetryPropertiesVar), ValueExpr.createNullExpr());

    List<Statement> updateRetrySettingsStatementBody = new ArrayList<>();

    for (Method method : Utils.getMethodsForRetryConfiguration(service)) {
      List<Statement> updateMethodWithServiceRetryStatements =
          createUpdateRetrySettingsStatements(
              method.name(), settingBuilderVariable, serviceRetryPropertiesVar, types);
      updateRetrySettingsStatementBody.addAll(updateMethodWithServiceRetryStatements);
      updateRetrySettingsStatementBody.add(EMPTY_LINE_STATEMENT);
    }

    updateRetrySettingsStatementBody.add(
        LoggerUtils.createLoggerStatement(
            ValueExpr.withValue(
                StringObjectValue.withValue(
                    "Configured service-level retry settings from properties.")),
            types));

    IfStatement setRetrySettingsStatement =
        createIfStatement(serviceRetryPropertiesNotNull, updateRetrySettingsStatementBody, null);

    bodyStatements.add(setRetrySettingsStatement);

    // If-blocks to update with method-level properties
    for (Method method : Utils.getMethodsForRetryConfiguration(service)) {
      String methodNameLowerCamel = JavaStyle.toLowerCamelCase(method.name());
      String methodNameUpperCamel = JavaStyle.toUpperCamelCase(method.name());

      Variable methodRetryPropertiesVar =
          Variable.builder()
              .setName(methodNameLowerCamel + "Retry")
              .setType(types.get("Retry"))
              .build();

      VariableExpr methodRetryPropertiesVarExpr =
          VariableExpr.builder().setVariable(methodRetryPropertiesVar).setIsDecl(true).build();

      // Method-level retry configuration: clientProperties.get<Method>Retry()
      MethodInvocationExpr methodRetryPropertiesExpr =
          MethodInvocationExpr.builder()
              .setExprReferenceExpr(VariableExpr.withVariable(clientPropertiesVar))
              .setMethodName(String.format("get%sRetry", methodNameUpperCamel))
              .setReturnType(types.get("Retry"))
              .build();

      AssignmentExpr methodRetrySettingsExpr =
          AssignmentExpr.builder()
              .setVariableExpr(methodRetryPropertiesVarExpr)
              .setValueExpr(methodRetryPropertiesExpr)
              .build();

      bodyStatements.add(ExprStatement.withExpr(methodRetrySettingsExpr));

      RelationalOperationExpr methodRetryPropertiesNotNull =
          RelationalOperationExpr.notEqualToWithExprs(
              VariableExpr.withVariable(methodRetryPropertiesVar), ValueExpr.createNullExpr());

      List<Statement> updateMethodRetrySettingsStatementBody =
          createUpdateRetrySettingsStatements(
              method.name(), settingBuilderVariable, methodRetryPropertiesVar, types);

      updateMethodRetrySettingsStatementBody.add(
          LoggerUtils.createLoggerStatement(
              ValueExpr.withValue(
                  StringObjectValue.withValue(
                      String.format(
                          "Configured method-level retry settings for %s from properties.",
                          methodNameLowerCamel))),
              types));

      IfStatement setMethodRetrySettingsStatement =
          createIfStatement(
              methodRetryPropertiesNotNull, updateMethodRetrySettingsStatementBody, null);

      bodyStatements.add(setMethodRetrySettingsStatement);
    }

    // return expressions
    MethodInvocationExpr returnExpr =
        MethodInvocationExpr.builder()
            .setMethodName("build")
            .setExprReferenceExpr(settingsVarExpr.toBuilder().setIsDecl(false).build())
            .setReturnType(types.get("ServiceSettings"))
            .build();
    List<VariableExpr> argumentsVariableExprs =
        Arrays.asList(
            transportChannelProviderVariableExpr
                .toBuilder()
                .setIsDecl(true)
                .setAnnotations(
                    Arrays.asList(
                        AnnotationNode.builder()
                            .setType(STATIC_TYPES.get("Qualifier"))
                            .setDescription(transportChannelProviderName)
                            .build()))
                .build());

    return MethodDefinition.builder()
        .setHeaderCommentStatements(
            SpringAutoconfigCommentComposer.createSettingsBeanComment(
                service,
                Utils.getServicePropertiesClassName(service),
                transportChannelProviderName))
        .setName(serviceSettingsMethodName)
        .setScope(ScopeNode.PUBLIC)
        .setReturnType(types.get("ServiceSettings"))
        .setArguments(argumentsVariableExprs)
        .setAnnotations(
            Arrays.asList(
                AnnotationNode.withType(STATIC_TYPES.get("Bean")),
                AnnotationNode.withType(STATIC_TYPES.get("ConditionalOnMissingBean"))))
        .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(IOException.class)))
        .setReturnExpr(returnExpr)
        .setBody(bodyStatements)
        .build();
  }