Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ public GapicClass generate(

ClassDefinition classDef =
ClassDefinition.builder()
.setHeaderCommentStatements(createClassHeaderComments(service, typeStore))
.setHeaderCommentStatements(
createClassHeaderComments(service, typeStore, resourceNames, messageTypes))
.setPackageString(pakkage)
.setAnnotations(createClassAnnotations(pakkage, typeStore))
.setScope(ScopeNode.PUBLIC)
Expand Down Expand Up @@ -161,17 +162,23 @@ private static List<TypeNode> createClassImplements(TypeStore typeStore) {
}

private static List<CommentStatement> createClassHeaderComments(
Service service, TypeStore typeStore) {
Service service,
TypeStore typeStore,
Map<String, ResourceName> resourceNames,
Map<String, Message> messageTypes) {
TypeNode clientType = typeStore.get(ClassNames.getServiceClientClassName(service));
TypeNode settingsType = typeStore.get(ClassNames.getServiceSettingsClassName(service));
String classMethodSampleCode =
ServiceClientSampleCodeComposer.composeClassHeaderMethodSampleCode(
service, clientType, resourceNames, messageTypes);
String credentialsSampleCode =
ServiceClientSampleCodeComposer.composeClassHeaderCredentialsSampleCode(
clientType, settingsType);
String endpointSampleCode =
ServiceClientSampleCodeComposer.composeClassHeaderEndpointSampleCode(
clientType, settingsType);
return ServiceClientCommentComposer.createClassHeaderComments(
service, credentialsSampleCode, endpointSampleCode);
service, classMethodSampleCode, credentialsSampleCode, endpointSampleCode);
}

private static List<MethodDefinition> createClassMethods(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ public class ServiceClientCommentComposer {
+ " operation returned by another API method call.");

public static List<CommentStatement> createClassHeaderComments(
Service service, String credentialsSampleCode, String endpointSampleCode) {
Service service,
String classMethodSampleCode,
String credentialsSampleCode,
String endpointSampleCode) {
JavaDocComment.Builder classHeaderJavadocBuilder = JavaDocComment.builder();
if (service.hasDescription()) {
classHeaderJavadocBuilder =
Expand All @@ -122,7 +125,7 @@ public static List<CommentStatement> createClassHeaderComments(

// Service introduction.
classHeaderJavadocBuilder.addParagraph(SERVICE_DESCRIPTION_INTRO_STRING);
// TODO(summerji): Add sample code here.
classHeaderJavadocBuilder.addSampleCode(classMethodSampleCode);

// API surface description.
classHeaderJavadocBuilder.addParagraph(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import com.google.api.generator.gapic.model.Method.Stream;
import com.google.api.generator.gapic.model.MethodArgument;
import com.google.api.generator.gapic.model.ResourceName;
import com.google.api.generator.gapic.model.Service;
import com.google.api.generator.gapic.utils.JavaStyle;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
Expand All @@ -64,6 +65,30 @@

public class ServiceClientSampleCodeComposer {

public static String composeClassHeaderMethodSampleCode(
Service service,
TypeNode clientType,
Map<String, ResourceName> resourceNames,
Map<String, Message> messageTypes) {
// Use the first pure unary RPC method's sample code as showcase, if no such method exists, use
// the first method in the service's methods list.
Method method =
service.methods().stream()
.filter(m -> m.stream() == Stream.NONE && !m.hasLro() && !m.isPaged())
.findFirst()
.orElse(service.methods().get(0));
if (method.stream() == Stream.NONE) {
if (method.methodSignatures().isEmpty()) {
return composeRpcDefaultMethodHeaderSampleCode(
method, clientType, resourceNames, messageTypes);
}
return composeRpcMethodHeaderSampleCode(
method, clientType, method.methodSignatures().get(0), resourceNames, messageTypes);
}
return composeStreamCallableMethodHeaderSampleCode(
method, clientType, resourceNames, messageTypes);
}

public static String composeClassHeaderCredentialsSampleCode(
TypeNode clientType, TypeNode settingsType) {
// Initialize clientSettings with builder() method.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ import javax.annotation.Generated;
* This class provides the ability to make remote calls to the backing service through method calls
* that map to API methods. Sample code to get started:
*
* <pre>{@code
* try (EchoClient echoClient = EchoClient.create()) {
* EchoResponse response = echoClient.echo();
* }
* }</pre>
*
* <p>Note: close() needs to be called on the EchoClient object to clean up resources such as
* threads. In the example above, try-with-resources is used, which automatically calls close().
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ import javax.annotation.Generated;
* This class provides the ability to make remote calls to the backing service through method calls
* that map to API methods. Sample code to get started:
*
* <pre>{@code
* try (IdentityClient identityClient = IdentityClient.create()) {
* String parent = UserName.of("[USER]").toString();
* String displayName = "displayName1714148973";
* String email = "email96619420";
* User response = identityClient.createUser(parent, displayName, email);
* }
* }</pre>
*
* <p>Note: close() needs to be called on the IdentityClient object to clean up resources such as
* threads. In the example above, try-with-resources is used, which automatically calls close().
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,19 @@
import com.google.api.generator.gapic.model.MethodArgument;
import com.google.api.generator.gapic.model.ResourceName;
import com.google.api.generator.gapic.model.ResourceReference;
import com.google.api.generator.gapic.model.Service;
import com.google.api.generator.gapic.protoparser.Parser;
import com.google.api.generator.testutils.LineFormatter;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.ServiceDescriptor;
import com.google.showcase.v1beta1.EchoOuterClass;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.junit.Test;

public class ServiceClientSampleCodeComposerTest {
Expand All @@ -46,6 +51,218 @@ public class ServiceClientSampleCodeComposerTest {
private static final String PROTO_PACKAGE_NAME = "com.google.protobuf";

// =============================== Class Header Sample Code ===============================//
@Test
public void composeClassHeaderMethodSampleCode_unaryRpc() {
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
ServiceDescriptor echoService = echoFileDescriptor.getServices().get(0);
Set<ResourceName> outputResourceNames = new HashSet<>();
List<Service> services =
Parser.parseService(
echoFileDescriptor, messageTypes, resourceNames, Optional.empty(), outputResourceNames);
Service echoProtoService = services.get(0);
TypeNode clientType =
TypeNode.withReference(
VaporReference.builder()
.setName("EchoClient")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
String results = ServiceClientSampleCodeComposer.composeClassHeaderMethodSampleCode(echoProtoService, clientType, resourceNames, messageTypes);
String expected =
LineFormatter.lines(
"try (EchoClient echoClient = EchoClient.create()) {\n",
" EchoResponse response = echoClient.echo();\n",
"}");
assertEquals(expected, results);
}

@Test
public void composeClassHeaderMethodSampleCode_firstMethodIsNotUnaryRpc() {
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
TypeNode inputType =
TypeNode.withReference(
VaporReference.builder()
.setName("WaitRequest")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
TypeNode outputType =
TypeNode.withReference(
VaporReference.builder().setName("Operation").setPakkage(LRO_PACKAGE_NAME).build());
TypeNode responseType =
TypeNode.withReference(
VaporReference.builder()
.setName("WaitResponse")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
TypeNode metadataType =
TypeNode.withReference(
VaporReference.builder()
.setName("WaitMetadata")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
LongrunningOperation lro = LongrunningOperation.withTypes(responseType, metadataType);
TypeNode ttlTypeNode =
TypeNode.withReference(
VaporReference.builder().setName("Duration").setPakkage(PROTO_PACKAGE_NAME).build());
MethodArgument ttl =
MethodArgument.builder()
.setName("ttl")
.setType(ttlTypeNode)
.setField(
Field.builder()
.setName("ttl")
.setType(ttlTypeNode)
.setIsMessage(true)
.setIsContainedInOneof(true)
.build())
.build();
Method method =
Method.builder()
.setName("Wait")
.setInputType(inputType)
.setOutputType(outputType)
.setLro(lro)
.setMethodSignatures(Arrays.asList(Arrays.asList(ttl)))
.build();
Service service = Service.builder()
.setName("Echo")
.setDefaultHost("localhost:7469")
.setOauthScopes(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"))
.setPakkage(SHOWCASE_PACKAGE_NAME)
.setProtoPakkage(SHOWCASE_PACKAGE_NAME)
.setOriginalJavaPackage(SHOWCASE_PACKAGE_NAME)
.setOverriddenName("Echo")
.setMethods(Arrays.asList(method))
.build();
TypeNode clientType =
TypeNode.withReference(
VaporReference.builder()
.setName("EchoClient")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
String results =
ServiceClientSampleCodeComposer.composeClassHeaderMethodSampleCode(
service, clientType, resourceNames, messageTypes);
String expected =
LineFormatter.lines(
"try (EchoClient echoClient = EchoClient.create()) {\n",
" Duration ttl = Duration.newBuilder().build();\n",
" WaitResponse response = echoClient.waitAsync(ttl).get();\n",
"}");
assertEquals(results, expected);
}

@Test
public void composeClassHeaderMethodSampleCode_firstMethodHasNoSignatures() {
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
TypeNode inputType =
TypeNode.withReference(
VaporReference.builder()
.setName("EchoRequest")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
TypeNode outputType =
TypeNode.withReference(
VaporReference.builder().setName("EchoResponse").setPakkage(SHOWCASE_PACKAGE_NAME).build());
Method method =
Method.builder()
.setName("Echo")
.setInputType(inputType)
.setOutputType(outputType)
.setMethodSignatures(Collections.emptyList())
.build();
Service service = Service.builder()
.setName("Echo")
.setDefaultHost("localhost:7469")
.setOauthScopes(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"))
.setPakkage(SHOWCASE_PACKAGE_NAME)
.setProtoPakkage(SHOWCASE_PACKAGE_NAME)
.setOriginalJavaPackage(SHOWCASE_PACKAGE_NAME)
.setOverriddenName("Echo")
.setMethods(Arrays.asList(method))
.build();
TypeNode clientType =
TypeNode.withReference(
VaporReference.builder()
.setName("EchoClient")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
String results =
ServiceClientSampleCodeComposer.composeClassHeaderMethodSampleCode(
service, clientType, resourceNames, messageTypes);
String expected =
LineFormatter.lines(
"try (EchoClient echoClient = EchoClient.create()) {\n",
" EchoRequest request =\n",
" EchoRequest.newBuilder()\n",
" .setName(FoobarName.ofProjectFoobarName(\"[PROJECT]\", \"[FOOBAR]\").toString())\n",
" .setParent(FoobarName.ofProjectFoobarName(\"[PROJECT]\", \"[FOOBAR]\").toString())\n",
" .setFoobar(Foobar.newBuilder().build())\n",
" .build();\n",
" EchoResponse response = echoClient.echo(request);\n",
"}");
assertEquals(results, expected);
}

@Test
public void composeClassHeaderMethodSampleCode_firstMethodIsStream() {
FileDescriptor echoFileDescriptor = EchoOuterClass.getDescriptor();
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(echoFileDescriptor);
Map<String, Message> messageTypes = Parser.parseMessages(echoFileDescriptor);
TypeNode inputType =
TypeNode.withReference(
VaporReference.builder()
.setName("ExpandRequest")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
TypeNode outputType =
TypeNode.withReference(
VaporReference.builder()
.setName("EchoResponse")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
Method method =
Method.builder()
.setName("Expand")
.setInputType(inputType)
.setOutputType(outputType)
.setStream(Stream.SERVER)
.build();
Service service = Service.builder()
.setName("Echo")
.setDefaultHost("localhost:7469")
.setOauthScopes(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"))
.setPakkage(SHOWCASE_PACKAGE_NAME)
.setProtoPakkage(SHOWCASE_PACKAGE_NAME)
.setOriginalJavaPackage(SHOWCASE_PACKAGE_NAME)
.setOverriddenName("Echo")
.setMethods(Arrays.asList(method))
.build();
TypeNode clientType =
TypeNode.withReference(
VaporReference.builder()
.setName("EchoClient")
.setPakkage(SHOWCASE_PACKAGE_NAME)
.build());
String results = ServiceClientSampleCodeComposer.composeClassHeaderMethodSampleCode(service, clientType, resourceNames, messageTypes);
String expected =
LineFormatter.lines(
"try (EchoClient echoClient = EchoClient.create()) {\n",
" ExpandRequest request =\n",
" ExpandRequest.newBuilder().setContent(\"content951530617\").setInfo(\"info3237038\").build();\n",
" ServerStream<EchoResponse> stream = echoClient.expandCallable().call(request);\n",
" for (EchoResponse response : stream) {\n",
" // Do something when a response is received.\n",
" }\n",
"}");
assertEquals(results, expected);
}

@Test
public void composeClassHeaderCredentialsSampleCode() {
TypeNode clientType =
Expand Down
12 changes: 12 additions & 0 deletions test/integration/goldens/asset/AssetServiceClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@
* <p>This class provides the ability to make remote calls to the backing service through method
* calls that map to API methods. Sample code to get started:
*
* <pre>{@code
* try (AssetServiceClient assetServiceClient = AssetServiceClient.create()) {
* BatchGetAssetsHistoryRequest request =
* BatchGetAssetsHistoryRequest.newBuilder()
* .setParent(FeedName.ofProjectFeedName("[PROJECT]", "[FEED]").toString())
* .addAllAssetNames(new ArrayList<String>())
* .setReadTimeWindow(TimeWindow.newBuilder().build())
* .build();
* BatchGetAssetsHistoryResponse response = assetServiceClient.batchGetAssetsHistory(request);
* }
* }</pre>
*
* <p>Note: close() needs to be called on the AssetServiceClient object to clean up resources such
* as threads. In the example above, try-with-resources is used, which automatically calls close().
*
Expand Down
Loading