Skip to content

Commit 051713d

Browse files
authored
feat: Add add autogenerated javadoc sample for selecting REST transport over gRPC (#983)
This is for grpc+rest clients. Also add proper grpc+rest unit tests which were missing.
1 parent 9e863f8 commit 051713d

25 files changed

+4577
-6
lines changed

src/main/java/com/google/api/generator/gapic/composer/comment/ServiceClientCommentComposer.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public class ServiceClientCommentComposer {
5555
"To customize credentials:";
5656
private static final String SERVICE_DESCRIPTION_ENDPOINT_SUMMARY_STRING =
5757
"To customize the endpoint:";
58+
private static final String SERVICE_DESCRIPTION_TRANSPORT_SUMMARY_STRING =
59+
"To use %s transport (instead of %s) for sending an receiving requests over the wire:";
5860

5961
private static final String SERVICE_DESCRIPTION_SAMPLE_REFERENCE_STRING =
6062
"Please refer to the GitHub repository's samples for more quickstart code snippets.";
@@ -112,7 +114,10 @@ public static List<CommentStatement> createClassHeaderComments(
112114
Service service,
113115
String classMethodSampleCode,
114116
String credentialsSampleCode,
115-
String endpointSampleCode) {
117+
String endpointSampleCode,
118+
String transportSampleCode,
119+
String primaryTransport,
120+
String secondaryTransport) {
116121
JavaDocComment.Builder classHeaderJavadocBuilder = JavaDocComment.builder();
117122
if (service.hasDescription()) {
118123
classHeaderJavadocBuilder =
@@ -146,6 +151,12 @@ public static List<CommentStatement> createClassHeaderComments(
146151
classHeaderJavadocBuilder.addSampleCode(credentialsSampleCode);
147152
classHeaderJavadocBuilder.addParagraph(SERVICE_DESCRIPTION_ENDPOINT_SUMMARY_STRING);
148153
classHeaderJavadocBuilder.addSampleCode(endpointSampleCode);
154+
if (transportSampleCode != null) {
155+
classHeaderJavadocBuilder.addParagraph(
156+
String.format(
157+
SERVICE_DESCRIPTION_TRANSPORT_SUMMARY_STRING, secondaryTransport, primaryTransport));
158+
classHeaderJavadocBuilder.addSampleCode(transportSampleCode);
159+
}
149160

150161
classHeaderJavadocBuilder.addParagraph(SERVICE_DESCRIPTION_SAMPLE_REFERENCE_STRING);
151162

src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ private static List<TypeNode> createClassImplements(TypeStore typeStore) {
188188
return Arrays.asList(typeStore.get("BackgroundResource"));
189189
}
190190

191-
private static List<CommentStatement> createClassHeaderComments(
191+
protected List<CommentStatement> createClassHeaderComments(
192192
Service service,
193193
TypeStore typeStore,
194194
Map<String, ResourceName> resourceNames,
@@ -208,7 +208,10 @@ private static List<CommentStatement> createClassHeaderComments(
208208
service,
209209
SampleCodeWriter.writeInlineSample(classMethodSampleCode.body()),
210210
SampleCodeWriter.writeInlineSample(credentialsSampleCode.body()),
211-
SampleCodeWriter.writeInlineSample(endpointSampleCode.body()));
211+
SampleCodeWriter.writeInlineSample(endpointSampleCode.body()),
212+
null,
213+
null,
214+
null);
212215
}
213216

214217
private List<MethodDefinition> createClassMethods(

src/main/java/com/google/api/generator/gapic/composer/grpcrest/ServiceClientClassComposer.java

+47
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,21 @@
1414

1515
package com.google.api.generator.gapic.composer.grpcrest;
1616

17+
import com.google.api.generator.engine.ast.CommentStatement;
18+
import com.google.api.generator.engine.ast.TypeNode;
19+
import com.google.api.generator.gapic.composer.comment.ServiceClientCommentComposer;
1720
import com.google.api.generator.gapic.composer.common.AbstractServiceClientClassComposer;
21+
import com.google.api.generator.gapic.composer.samplecode.SampleCodeWriter;
22+
import com.google.api.generator.gapic.composer.samplecode.ServiceClientHeaderSampleComposer;
23+
import com.google.api.generator.gapic.composer.store.TypeStore;
24+
import com.google.api.generator.gapic.composer.utils.ClassNames;
25+
import com.google.api.generator.gapic.model.Message;
26+
import com.google.api.generator.gapic.model.ResourceName;
27+
import com.google.api.generator.gapic.model.Sample;
28+
import com.google.api.generator.gapic.model.Service;
29+
import java.util.Arrays;
30+
import java.util.List;
31+
import java.util.Map;
1832

1933
public class ServiceClientClassComposer extends AbstractServiceClientClassComposer {
2034
private static final ServiceClientClassComposer INSTANCE = new ServiceClientClassComposer();
@@ -26,4 +40,37 @@ protected ServiceClientClassComposer() {
2640
public static ServiceClientClassComposer instance() {
2741
return INSTANCE;
2842
}
43+
44+
@Override
45+
protected List<CommentStatement> createClassHeaderComments(
46+
Service service,
47+
TypeStore typeStore,
48+
Map<String, ResourceName> resourceNames,
49+
Map<String, Message> messageTypes,
50+
List<Sample> samples) {
51+
TypeNode clientType = typeStore.get(ClassNames.getServiceClientClassName(service));
52+
TypeNode settingsType = typeStore.get(ClassNames.getServiceSettingsClassName(service));
53+
Sample classMethodSampleCode =
54+
ServiceClientHeaderSampleComposer.composeClassHeaderSample(
55+
service, clientType, resourceNames, messageTypes);
56+
Sample credentialsSampleCode =
57+
ServiceClientHeaderSampleComposer.composeSetCredentialsSample(clientType, settingsType);
58+
Sample endpointSampleCode =
59+
ServiceClientHeaderSampleComposer.composeSetEndpointSample(clientType, settingsType);
60+
Sample transportSampleCode =
61+
ServiceClientHeaderSampleComposer.composeTransportSample(
62+
clientType, settingsType, "defaultHttpJsonTransportProviderBuilder");
63+
samples.addAll(
64+
Arrays.asList(
65+
classMethodSampleCode, credentialsSampleCode, endpointSampleCode, transportSampleCode));
66+
67+
return ServiceClientCommentComposer.createClassHeaderComments(
68+
service,
69+
SampleCodeWriter.writeInlineSample(classMethodSampleCode.body()),
70+
SampleCodeWriter.writeInlineSample(credentialsSampleCode.body()),
71+
SampleCodeWriter.writeInlineSample(endpointSampleCode.body()),
72+
SampleCodeWriter.writeInlineSample(transportSampleCode.body()),
73+
"gRPC",
74+
"REST (HTTP1.1/JSON)");
75+
}
2976
}

src/main/java/com/google/api/generator/gapic/composer/samplecode/ServiceClientHeaderSampleComposer.java

+70
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,76 @@ public static Sample composeSetEndpointSample(TypeNode clientType, TypeNode sett
277277
return Sample.builder().setBody(sampleBody).setRegionTag(regionTag).build();
278278
}
279279

280+
public static Sample composeTransportSample(
281+
TypeNode clientType, TypeNode settingsType, String transportProviderMethod) {
282+
String settingsName = JavaStyle.toLowerCamelCase(settingsType.reference().name());
283+
String clientName = JavaStyle.toLowerCamelCase(clientType.reference().name());
284+
VariableExpr settingsVarExpr =
285+
VariableExpr.withVariable(
286+
Variable.builder().setName(settingsName).setType(settingsType).build());
287+
MethodInvocationExpr newBuilderMethodExpr =
288+
MethodInvocationExpr.builder()
289+
.setStaticReferenceType(settingsType)
290+
.setMethodName("newBuilder")
291+
.build();
292+
MethodInvocationExpr transportChannelProviderArg =
293+
MethodInvocationExpr.builder()
294+
.setExprReferenceExpr(
295+
MethodInvocationExpr.builder()
296+
.setStaticReferenceType(settingsType)
297+
.setMethodName(transportProviderMethod)
298+
.build())
299+
.setMethodName("build")
300+
.build();
301+
MethodInvocationExpr credentialsMethodExpr =
302+
MethodInvocationExpr.builder()
303+
.setExprReferenceExpr(newBuilderMethodExpr)
304+
.setArguments(transportChannelProviderArg)
305+
.setMethodName("setTransportChannelProvider")
306+
.build();
307+
MethodInvocationExpr buildMethodExpr =
308+
MethodInvocationExpr.builder()
309+
.setExprReferenceExpr(credentialsMethodExpr)
310+
.setReturnType(settingsType)
311+
.setMethodName("build")
312+
.build();
313+
Expr initSettingsVarExpr =
314+
AssignmentExpr.builder()
315+
.setVariableExpr(settingsVarExpr.toBuilder().setIsDecl(true).build())
316+
.setValueExpr(buildMethodExpr)
317+
.build();
318+
319+
// Initialized client with create() method.
320+
// e.g. EchoClient echoClient = EchoClient.create(echoSettings);
321+
VariableExpr clientVarExpr =
322+
VariableExpr.withVariable(
323+
Variable.builder().setName(clientName).setType(clientType).build());
324+
MethodInvocationExpr createMethodExpr =
325+
MethodInvocationExpr.builder()
326+
.setStaticReferenceType(clientType)
327+
.setArguments(settingsVarExpr)
328+
.setMethodName("create")
329+
.setReturnType(clientType)
330+
.build();
331+
String rpcName = createMethodExpr.methodIdentifier().name();
332+
Expr initClientVarExpr =
333+
AssignmentExpr.builder()
334+
.setVariableExpr(clientVarExpr.toBuilder().setIsDecl(true).build())
335+
.setValueExpr(createMethodExpr)
336+
.build();
337+
338+
List<Statement> sampleBody =
339+
Arrays.asList(
340+
ExprStatement.withExpr(initSettingsVarExpr), ExprStatement.withExpr(initClientVarExpr));
341+
RegionTag regionTag =
342+
RegionTag.builder()
343+
.setServiceName(clientName)
344+
.setRpcName(rpcName)
345+
.setOverloadDisambiguation("setCredentialsProvider")
346+
.build();
347+
return Sample.builder().setBody(sampleBody).setRegionTag(regionTag).build();
348+
}
349+
280350
// Create a list of RPC method arguments' variable expressions.
281351
private static List<VariableExpr> createArgumentVariableExprs(List<MethodArgument> arguments) {
282352
return arguments.stream()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator.gapic.composer.grpcrest;
16+
17+
import static org.junit.Assert.assertEquals;
18+
import static org.junit.Assert.assertTrue;
19+
20+
import com.google.api.generator.gapic.composer.common.TestProtoLoader;
21+
import com.google.api.generator.gapic.model.GapicContext;
22+
import com.google.api.generator.gapic.model.GapicServiceConfig;
23+
import com.google.api.generator.gapic.model.Message;
24+
import com.google.api.generator.gapic.model.ResourceName;
25+
import com.google.api.generator.gapic.model.Service;
26+
import com.google.api.generator.gapic.model.Transport;
27+
import com.google.api.generator.gapic.protoparser.Parser;
28+
import com.google.api.generator.gapic.protoparser.ServiceConfigParser;
29+
import com.google.longrunning.OperationsProto;
30+
import com.google.protobuf.Descriptors.FileDescriptor;
31+
import com.google.protobuf.Descriptors.ServiceDescriptor;
32+
import com.google.showcase.grpcrest.v1beta1.EchoGrpcrest;
33+
import java.nio.file.Path;
34+
import java.nio.file.Paths;
35+
import java.util.HashSet;
36+
import java.util.List;
37+
import java.util.Map;
38+
import java.util.Optional;
39+
import java.util.Set;
40+
41+
public class GrpcRestTestProtoLoader extends TestProtoLoader {
42+
private static final GrpcRestTestProtoLoader INSTANCE = new GrpcRestTestProtoLoader();
43+
44+
protected GrpcRestTestProtoLoader() {
45+
super(Transport.GRPC_REST, "src/test/resources/");
46+
}
47+
48+
public static GrpcRestTestProtoLoader instance() {
49+
return INSTANCE;
50+
}
51+
52+
@Override
53+
public GapicContext parseShowcaseEcho() {
54+
FileDescriptor echoFileDescriptor = EchoGrpcrest.getDescriptor();
55+
56+
ServiceDescriptor echoServiceDescriptor = echoFileDescriptor.getServices().get(0);
57+
assertEquals("Echo", echoServiceDescriptor.getName());
58+
59+
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
60+
Map<String, Message> operationMessageTypes =
61+
Parser.parseMessages(OperationsProto.getDescriptor());
62+
messageTypes.putAll(operationMessageTypes);
63+
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
64+
Set<ResourceName> outputResourceNames = new HashSet<>();
65+
List<Service> services =
66+
Parser.parseService(
67+
echoFileDescriptor, messageTypes, resourceNames, Optional.empty(), outputResourceNames);
68+
69+
String jsonFilename = "showcase_grpc_service_config.json";
70+
Path jsonPath = Paths.get(getTestFilesDirectory(), jsonFilename);
71+
Optional<GapicServiceConfig> configOpt = ServiceConfigParser.parse(jsonPath.toString());
72+
assertTrue(configOpt.isPresent());
73+
GapicServiceConfig config = configOpt.get();
74+
75+
return GapicContext.builder()
76+
.setMessages(messageTypes)
77+
.setResourceNames(resourceNames)
78+
.setServices(services)
79+
.setServiceConfig(config)
80+
.setHelperResourceNames(outputResourceNames)
81+
.setTransport(getTransport())
82+
.build();
83+
}
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator.gapic.composer.grpcrest;
16+
17+
import com.google.api.generator.engine.writer.JavaWriterVisitor;
18+
import com.google.api.generator.gapic.composer.grpc.GrpcServiceCallableFactoryClassComposer;
19+
import com.google.api.generator.gapic.model.GapicClass;
20+
import com.google.api.generator.gapic.model.GapicContext;
21+
import com.google.api.generator.gapic.model.Service;
22+
import com.google.api.generator.test.framework.Assert;
23+
import com.google.api.generator.test.framework.Utils;
24+
import java.nio.file.Path;
25+
import java.nio.file.Paths;
26+
import org.junit.Test;
27+
28+
public class GrpcServiceCallableFactoryClassComposerTest {
29+
@Test
30+
public void generateServiceClasses() {
31+
GapicContext context = GrpcRestTestProtoLoader.instance().parseShowcaseEcho();
32+
Service echoProtoService = context.services().get(0);
33+
GapicClass clazz =
34+
GrpcServiceCallableFactoryClassComposer.instance().generate(context, echoProtoService);
35+
36+
JavaWriterVisitor visitor = new JavaWriterVisitor();
37+
clazz.classDefinition().accept(visitor);
38+
Utils.saveCodegenToFile(this.getClass(), "GrpcEchoCallableFactory.golden", visitor.write());
39+
Path goldenFilePath =
40+
Paths.get(Utils.getGoldenDir(this.getClass()), "GrpcEchoCallableFactory.golden");
41+
Assert.assertCodeEquals(goldenFilePath, visitor.write());
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator.gapic.composer.grpcrest;
16+
17+
import com.google.api.generator.engine.writer.JavaWriterVisitor;
18+
import com.google.api.generator.gapic.composer.grpc.GrpcServiceStubClassComposer;
19+
import com.google.api.generator.gapic.model.GapicClass;
20+
import com.google.api.generator.gapic.model.GapicContext;
21+
import com.google.api.generator.gapic.model.Service;
22+
import com.google.api.generator.test.framework.Assert;
23+
import com.google.api.generator.test.framework.Utils;
24+
import java.nio.file.Path;
25+
import java.nio.file.Paths;
26+
import org.junit.Test;
27+
28+
public class GrpcServiceStubClassComposerTest {
29+
@Test
30+
public void generateServiceClasses() {
31+
GapicContext context = GrpcRestTestProtoLoader.instance().parseShowcaseEcho();
32+
Service echoProtoService = context.services().get(0);
33+
GapicClass clazz = GrpcServiceStubClassComposer.instance().generate(context, echoProtoService);
34+
35+
JavaWriterVisitor visitor = new JavaWriterVisitor();
36+
clazz.classDefinition().accept(visitor);
37+
Utils.saveCodegenToFile(this.getClass(), "GrpcEchoStub.golden", visitor.write());
38+
Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "GrpcEchoStub.golden");
39+
Assert.assertCodeEquals(goldenFilePath, visitor.write());
40+
}
41+
}

0 commit comments

Comments
 (0)