diff --git a/src/main/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposer.java b/src/main/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposer.java index aba9ec3c97..59e5e19daf 100644 --- a/src/main/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposer.java +++ b/src/main/java/com/google/api/generator/spring/composer/SpringAutoConfigClassComposer.java @@ -32,9 +32,11 @@ import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.NewObjectExpr; +import com.google.api.generator.engine.ast.PrimitiveValue; import com.google.api.generator.engine.ast.RelationalOperationExpr; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.Statement; +import com.google.api.generator.engine.ast.StringObjectValue; import com.google.api.generator.engine.ast.ThisObjectValue; import com.google.api.generator.engine.ast.TypeNode; import com.google.api.generator.engine.ast.ValueExpr; @@ -401,24 +403,54 @@ private static List createClassAnnotations( // @ConditionalOnProperty(value = "spring.cloud.gcp.language.enabled", matchIfMissing = true) // @EnableConfigurationProperties(LanguageProperties.class) - // TODO: AnnotationNode description only accepts String for now. need to extend to params - // and classes. + AssignmentExpr valueStringAssignmentExpr = + AssignmentExpr.builder() + .setVariableExpr( + VariableExpr.withVariable( + Variable.builder().setName("value").setType(TypeNode.STRING).build())) + .setValueExpr( + ValueExpr.withValue( + StringObjectValue.withValue( + Utils.springPropertyPrefix(libName, service.name()) + ".enabled"))) + .build(); + AssignmentExpr matchIfMissingAssignmentExpr = + AssignmentExpr.builder() + .setVariableExpr( + VariableExpr.withVariable( + Variable.builder().setName("matchIfMissing").setType(TypeNode.BOOLEAN).build())) + .setValueExpr( + ValueExpr.withValue( + PrimitiveValue.builder().setValue("false").setType(TypeNode.BOOLEAN).build())) + .build(); AnnotationNode conditionalOnPropertyNode = AnnotationNode.builder() .setType(types.get("ConditionalOnProperty")) - .setDescription( - "value = \"" - + Utils.springPropertyPrefix(libName, service.name()) - + ".enabled\", matchIfMissing = false") + .addDescription(valueStringAssignmentExpr) + .addDescription(matchIfMissingAssignmentExpr) .build(); + AnnotationNode conditionalOnClassNode = AnnotationNode.builder() .setType(types.get("ConditionalOnClass")) .setDescription( - "value = " - + ClassNames.getServiceClientClassName(service) - + ".class") // TODO: change after annotation feature merged. need to produce - // XXX.class + VariableExpr.builder() + .setVariable( + Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) + .setStaticReferenceType(types.get("ServiceClient")) + .build()) + .build(); + + AssignmentExpr proxyBeanMethodsAssignmentExpr = + AssignmentExpr.builder() + .setVariableExpr( + VariableExpr.withVariable( + Variable.builder() + .setName("proxyBeanMethods") + .setType(TypeNode.BOOLEAN) + .build())) + .setValueExpr( + ValueExpr.withValue( + PrimitiveValue.builder().setValue("false").setType(TypeNode.BOOLEAN).build())) .build(); AnnotationNode configurationNode = AnnotationNode.builder().setType(types.get("AutoConfiguration")).build(); @@ -426,9 +458,13 @@ private static List createClassAnnotations( AnnotationNode.builder() .setType(types.get("EnableConfigurationProperties")) .setDescription( - types.get(service.name() + "Properties").reference().name() - + ".Class") // TODO: change to parameters + VariableExpr.builder() + .setVariable( + Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) + .setStaticReferenceType(types.get(service.name() + "Properties")) + .build()) .build(); + return Arrays.asList( AnnotationNode.builder() .setType(STATIC_TYPES.get("Generated")) @@ -893,14 +929,35 @@ private static MethodDefinition createClientBeanMethod( String methodName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, service.name()) + "Client"; + String transportChannelProviderName = "default" + service.name() + "TransportChannelProvider"; + String credentialsProviderName = "googleCredentials"; + return MethodDefinition.builder() .setName(methodName) .setScope(ScopeNode.PUBLIC) .setReturnType(types.get("ServiceClient")) .setArguments( Arrays.asList( - credentialsProviderVariableExpr.toBuilder().setIsDecl(true).build(), - transportChannelProviderVariableExpr.toBuilder().setIsDecl(true).build())) + credentialsProviderVariableExpr + .toBuilder() + .setIsDecl(true) + .setAnnotations( + Arrays.asList( + AnnotationNode.builder() + .setType(types.get("Qualifier")) + .setDescription(credentialsProviderName) + .build())) + .build(), + transportChannelProviderVariableExpr + .toBuilder() + .setIsDecl(true) + .setAnnotations( + Arrays.asList( + AnnotationNode.builder() + .setType(types.get("Qualifier")) + .setDescription(transportChannelProviderName) + .build())) + .build())) .setAnnotations( Arrays.asList( AnnotationNode.withType(types.get("Bean")), @@ -1049,6 +1106,13 @@ private static Map createDynamicTypes(Service service, String .setPakkage("org.springframework.boot.autoconfigure.condition") .build()); + TypeNode qualifier = + TypeNode.withReference( + VaporReference.builder() + .setName("Qualifier") + .setPakkage("org.springframework.beans.factory.annotation") + .build()); + typeMap.put("CredentialsProvider", credentialsProvider); typeMap.put(service.name() + "Properties", clientProperties); typeMap.put(service.name() + "AutoConfig", clientAutoconfig); @@ -1064,6 +1128,7 @@ private static Map createDynamicTypes(Service service, String typeMap.put("ConditionalOnMissingBean", conditionalOnMissingBean); typeMap.put("ConditionalOnProperty", conditionalOnProperty); typeMap.put("ConditionalOnClass", conditionalOnClass); + typeMap.put("Qualifier", qualifier); return typeMap; } diff --git a/src/main/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposer.java b/src/main/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposer.java index 949e34c4de..aff2bcbe2d 100644 --- a/src/main/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposer.java +++ b/src/main/java/com/google/api/generator/spring/composer/SpringPropertiesClassComposer.java @@ -92,12 +92,17 @@ public GapicClass generate(GapicContext context, Service service) { } private static ExprStatement createMemberVarStatement( - String varName, TypeNode varType, boolean isFinal, Expr defaultVal) { + String varName, + TypeNode varType, + boolean isFinal, + Expr defaultVal, + List annotationNodes) { Variable memberVar = Variable.builder().setName(varName).setType(varType).build(); VariableExpr memberVarExpr = VariableExpr.builder() .setVariable(memberVar) .setScope(ScopeNode.PRIVATE) + .setAnnotations(annotationNodes == null ? Collections.emptyList() : annotationNodes) .setIsDecl(true) .setIsFinal(isFinal) .build(); @@ -133,22 +138,30 @@ private static List createMemberVariables( .map(x -> ValueExpr.withValue(StringObjectValue.withValue(x))) .collect(Collectors.toList())) .build(); - // TODO: credentials field needs annotation. + // Note that the annotations are set on the VariableExpr rather than the ExprStatement. + // The single annotation works fine here, + // but multiple annotations would be written to the same line + List credentialsAnnotations = + Arrays.asList(AnnotationNode.withType(types.get("NestedConfigurationProperty"))); ExprStatement credentialsStatement = createMemberVarStatement( - "credentials", types.get("Credentials"), true, defaultCredentialScopes); + "credentials", + types.get("Credentials"), + true, + defaultCredentialScopes, + credentialsAnnotations); // private String quotaProjectId; ExprStatement quotaProjectIdVarStatement = - createMemberVarStatement("quotaProjectId", TypeNode.STRING, false, null); + createMemberVarStatement("quotaProjectId", TypeNode.STRING, false, null, null); // private Integer executorThreadCount; ExprStatement executorThreadCountVarStatement = - createMemberVarStatement("executorThreadCount", TypeNode.INT_OBJECT, false, null); + createMemberVarStatement("executorThreadCount", TypeNode.INT_OBJECT, false, null, null); // private boolean useRest = false; ExprStatement useRestVarStatement = - createMemberVarStatement("useRest", TypeNode.BOOLEAN, false, null); + createMemberVarStatement("useRest", TypeNode.BOOLEAN, false, null, null); // // private static final ImmutableMap RETRY_PARAM_DEFINITIONS; @@ -170,7 +183,7 @@ private static List createMemberVariables( } String propertyName = Joiner.on("").join(methodAndPropertyName); ExprStatement retrySettingsStatement = - createMemberVarStatement(propertyName, propertyType, false, null); + createMemberVarStatement(propertyName, propertyType, false, null, null); getterAndSetter.add(retrySettingsStatement); return getterAndSetter; }, diff --git a/src/test/java/com/google/api/generator/spring/SpringAutoConfigClassComposerTest.java b/src/test/java/com/google/api/generator/spring/SpringAutoConfigClassComposerTest.java index 8fef5ea0a5..2a402e3f96 100644 --- a/src/test/java/com/google/api/generator/spring/SpringAutoConfigClassComposerTest.java +++ b/src/test/java/com/google/api/generator/spring/SpringAutoConfigClassComposerTest.java @@ -153,10 +153,11 @@ public void generatePropertiesTest() { + "\n" + "@Generated(\"by gapic-generator-java\")\n" + "@AutoConfiguration\n" - + "@ConditionalOnClass(\"value = EchoClient.class\")\n" + + "@ConditionalOnClass(EchoClient.class)\n" + "@ConditionalOnProperty(\n" - + " \"value = \\\"spring.cloud.gcp.autoconfig.showcase.echo.enabled\\\", matchIfMissing = false\")\n" - + "@EnableConfigurationProperties(\"EchoSpringProperties.Class\")\n" + + " value = \"spring.cloud.gcp.autoconfig.showcase.echo.enabled\",\n" + + " matchIfMissing = false)\n" + + "@EnableConfigurationProperties(EchoSpringProperties.class)\n" + "public class EchoSpringAutoConfiguration {\n" + " private final EchoSpringProperties clientProperties;\n" + " private static final ImmutableMap RETRY_PARAM_DEFINITIONS;\n" @@ -189,8 +190,9 @@ public void generatePropertiesTest() { + " @Bean\n" + " @ConditionalOnMissingBean\n" + " public EchoClient echoClient(\n" - + " CredentialsProvider credentialsProvider,\n" - + " TransportChannelProvider defaultTransportChannelProvider)\n" + + " @Qualifier(\"googleCredentials\") CredentialsProvider credentialsProvider,\n" + + " @Qualifier(\"defaultEchoTransportChannelProvider\")\n" + + " TransportChannelProvider defaultTransportChannelProvider)\n" + " throws IOException {\n" + " EchoSettings.Builder clientSettingsBuilder =\n" + " EchoSettings.newBuilder()\n" @@ -303,8 +305,10 @@ public void generatePropertiesTest() { + "\n" + "@ConfigurationProperties(\"spring.cloud.gcp.autoconfig.showcase.echo\")\n" + "public class EchoSpringProperties implements CredentialsSupplier {\n" + + " @NestedConfigurationProperty\n" + " private final Credentials credentials =\n" + " new Credentials(\"https://www.googleapis.com/auth/cloud-platform\");\n" + + "\n" + " private String quotaProjectId;\n" + " private Integer executorThreadCount;\n" + " private boolean useRest;\n"